]> 127.0.0.1 Git - part/.git/commitdiff
1 (#24) v0.28.20250211194255
authorqydysky <qydysky@foxmail.com>
Tue, 11 Feb 2025 19:42:42 +0000 (03:42 +0800)
committerGitHub <noreply@github.com>
Tue, 11 Feb 2025 19:42:42 +0000 (03:42 +0800)
* 1

* 1

* 1

* 1

errors/errors.go
msgq/Msgq.go
sync/RWMutex.go
sync/RWMutex_test.go

index fe1e39d15d00b94bc7f5af725a508ccfba698795..ab72a030248ac7f7f3c64f3e3c82c47f961ba903 100644 (file)
@@ -21,8 +21,11 @@ func (t Action) New(reason ...string) (e Error) {
        return
 }
 
+func (t Action) Error() string {
+       return string(t)
+}
+
 type Error struct {
-       son    error
        Reason string
        action Action
 }
index d2f732af061f2574c6f82983b0119a330a1a4319..d3c8e769be4122cf25e79102d1bcacbe6464ca4c 100644 (file)
@@ -81,7 +81,7 @@ func (m *Msgq) Register_front(f func(any) (disable bool)) (cancel func()) {
 
 func (m *Msgq) Push(msg any) {
        ul := m.lock.RLock(m.to...)
-       defer ul(m.removeDisable)
+       defer ul(m.removeDisable(true)...)
 
        for el := m.funcs.Front(); el != nil; el = el.Next() {
                mi := el.Value.(*msgqItem)
@@ -99,7 +99,7 @@ func (m *Msgq) Push(msg any) {
 
 func (m *Msgq) PushLock(msg any) {
        ul := m.lock.Lock(m.to...)
-       defer ul(m.removeDisable)
+       defer ul(m.removeDisable(false)...)
 
        for el := m.funcs.Front(); el != nil; el = el.Next() {
                mi := el.Value.(*msgqItem)
@@ -123,15 +123,38 @@ func (m *Msgq) ClearAll() {
        }
 }
 
-func (m *Msgq) removeDisable() {
-       if !m.someNeedRemove.CompareAndSwap(true, false) {
-               return
-       }
-
-       for el := m.funcs.Front(); el != nil; el = el.Next() {
-               mi := el.Value.(*msgqItem)
-               if mi.disable.Load() && mi.running.Load() == 0 {
-                       m.funcs.Remove(el)
+func (m *Msgq) removeDisable(rlock bool) (ls []func(ulocked bool) (doUlock bool)) {
+       if rlock {
+               return []func(ulocked bool) (doUlock bool){
+                       func(ulocked bool) (doUlock bool) {
+                               return m.someNeedRemove.CompareAndSwap(true, false)
+                       },
+                       func(ulocked bool) (doUlock bool) {
+                               if ulocked {
+                                       defer m.lock.Lock()()
+                                       for el := m.funcs.Front(); el != nil; el = el.Next() {
+                                               mi := el.Value.(*msgqItem)
+                                               if mi.disable.Load() && mi.running.Load() == 0 {
+                                                       m.funcs.Remove(el)
+                                               }
+                                       }
+                               }
+                               return
+                       },
+               }
+       } else {
+               return []func(ulocked bool) (doUlock bool){
+                       func(ulocked bool) (doUlock bool) {
+                               if m.someNeedRemove.CompareAndSwap(true, false) {
+                                       for el := m.funcs.Front(); el != nil; el = el.Next() {
+                                               mi := el.Value.(*msgqItem)
+                                               if mi.disable.Load() && mi.running.Load() == 0 {
+                                                       m.funcs.Remove(el)
+                                               }
+                                       }
+                               }
+                               return
+                       },
                }
        }
 }
@@ -169,7 +192,7 @@ func (m *Msgq) Push_tag(Tag string, Data any) {
                                Data: Data,
                        })
                */
-               defer m.lock.RLock(m.to...)(m.removeDisable)
+               defer m.lock.RLock(m.to...)(m.removeDisable(true)...)
 
                for el := m.funcs.Front(); el != nil; el = el.Next() {
                        mi := el.Value.(*msgqItem)
@@ -218,7 +241,7 @@ func (m *Msgq) PushLock_tag(Tag string, Data any) {
                        })
                */
                ul := m.lock.Lock(m.to...)
-               defer ul(m.removeDisable)
+               defer ul(m.removeDisable(false)...)
 
                for el := m.funcs.Front(); el != nil; el = el.Next() {
                        mi := el.Value.(*msgqItem)
@@ -376,7 +399,7 @@ func (m *MsgType[T]) Push_tag(Tag string, Data T) {
                        })
                */
                ul := m.m.lock.RLock(m.m.to...)
-               defer ul(m.m.removeDisable)
+               defer ul(m.m.removeDisable(true)...)
 
                for el := m.m.funcs.Front(); el != nil; el = el.Next() {
                        mi := el.Value.(*msgqItem)
@@ -425,7 +448,7 @@ func (m *MsgType[T]) PushLock_tag(Tag string, Data T) {
                        })
                */
                ul := m.m.lock.Lock(m.m.to...)
-               defer ul(m.m.removeDisable)
+               defer ul(m.m.removeDisable(false)...)
 
                for el := m.m.funcs.Front(); el != nil; el = el.Next() {
                        mi := el.Value.(*msgqItem)
index 9f787c27cd0d972d01ea7eba4fe563a977c26c03..2794493a5899a345115c038099497e4b946ec9d9 100644 (file)
@@ -86,42 +86,60 @@ func (m *RWMutex) tof(to time.Duration, e error) (inTimeCall func() (called bool
 // to[1]: wait ulock timeout
 //
 // 不要在Rlock内设置变量,有DATA RACE风险
-func (m *RWMutex) RLock(to ...time.Duration) (unlockf func(beforeUlock ...func())) {
+func (m *RWMutex) RLock(to ...time.Duration) (unlockf func(ulockfs ...func(ulocked bool) (doUlock bool))) {
        if len(to) > 0 {
                defer m.tof(to[0], ErrTimeoutToLock)()
        }
 
        m.rlc.RLock()
 
-       return func(beforeUlock ...func()) {
+       return func(ulockfs ...func(ulocked bool) (doUlock bool)) {
+               inTimeCall := func() (called bool) { return true }
                if len(to) > 1 {
-                       defer m.tof(to[1], ErrTimeoutToULock)()
+                       inTimeCall = m.tof(to[1], ErrTimeoutToULock)
                }
-               for i := 0; i < len(beforeUlock); i++ {
-                       beforeUlock[i]()
+               ul := false
+               for i := 0; i < len(ulockfs); i++ {
+                       if ulockfs[i](ul) && !ul {
+                               m.rlc.RUnlock()
+                               inTimeCall()
+                               ul = true
+                       }
+               }
+               if !ul {
+                       m.rlc.RUnlock()
+                       inTimeCall()
                }
-               m.rlc.RUnlock()
        }
 }
 
 // to[0]: wait lock timeout
 //
 // to[1]: wait ulock timeout
-func (m *RWMutex) Lock(to ...time.Duration) (unlockf func(beforeUlock ...func())) {
+func (m *RWMutex) Lock(to ...time.Duration) (unlockf func(ulockfs ...func(ulocked bool) (doUlock bool))) {
        if len(to) > 0 {
                defer m.tof(to[0], ErrTimeoutToLock)()
        }
 
        m.rlc.Lock()
 
-       return func(beforeUlock ...func()) {
+       return func(ulockfs ...func(ulocked bool) (doUlock bool)) {
+               inTimeCall := func() (called bool) { return true }
                if len(to) > 1 {
-                       defer m.tof(to[1], ErrTimeoutToULock)()
+                       inTimeCall = m.tof(to[1], ErrTimeoutToULock)
+               }
+               ul := false
+               for i := 0; i < len(ulockfs); i++ {
+                       if ulockfs[i](ul) && !ul {
+                               m.rlc.Unlock()
+                               inTimeCall()
+                               ul = true
+                       }
                }
-               for i := 0; i < len(beforeUlock); i++ {
-                       beforeUlock[i]()
+               if !ul {
+                       m.rlc.Unlock()
+                       inTimeCall()
                }
-               m.rlc.Unlock()
        }
 }
 
index fb56fbd4473c8fb4f227c248714195d9b4b390b3..fb437d9201f9078f26a186d9239e1c70d7907648 100644 (file)
@@ -42,9 +42,10 @@ func Test1(t *testing.T) {
 func Test4(t *testing.T) {
        var l RWMutex
        ul := l.RLock()
-       ul(func() {
+       ul(func(ulocked bool) (doUlock bool) {
                ul1 := l.RLock()
                ul1()
+               return true
        })
 }
 
@@ -55,8 +56,9 @@ func Test5(t *testing.T) {
                }
        }}
        ul := l.RLock(time.Second, time.Second)
-       ul(func() {
+       ul(func(ulocked bool) (doUlock bool) {
                time.Sleep(time.Second * 2)
+               return true
        })
 }
 
@@ -67,7 +69,7 @@ func Test8(t *testing.T) {
                }
        }}
        ul := l.Lock()
-       go ul(func() { time.Sleep(time.Second) })
+       go ul(func(ulocked bool) (doUlock bool) { time.Sleep(time.Second); return true })
        ul1 := l.RLock(time.Millisecond*500, time.Second)
        ul1()
 }
@@ -120,8 +122,9 @@ func Test6(t *testing.T) {
                ul1()
                c <- 2
        })
-       ul(func() {
+       ul(func(ulocked bool) (doUlock bool) {
                time.Sleep(time.Second)
+               return true
        })
        c <- 0
        if <-c != 1 {
@@ -140,11 +143,13 @@ func Test7(t *testing.T) {
        var l RWMutex
        ul := l.RLock()
        ul1 := l.RLock()
-       ul(func() {
+       ul(func(ulocked bool) (doUlock bool) {
                c <- 0
+               return true
        })
-       ul1(func() {
+       ul1(func(ulocked bool) (doUlock bool) {
                c <- 1
+               return true
        })
        if <-c != 0 {
                t.Fatal()
@@ -176,8 +181,9 @@ func Test10(t *testing.T) {
 func Panic_Test8(t *testing.T) {
        var l RWMutex
        ul := l.Lock(time.Second, time.Second)
-       ul(func() {
+       ul(func(ulocked bool) (doUlock bool) {
                time.Sleep(time.Second * 10)
+               return true
        })
 }
 
@@ -226,6 +232,17 @@ BenchmarkRlock-4
 
        1000000              1069 ns/op              24 B/op          1 allocs/op
 
+# PASS
+
+goos: linux
+goarch: amd64
+pkg: github.com/qydysky/part/sync
+cpu: Intel(R) N100
+BenchmarkRlock
+BenchmarkRlock-4
+
+       4493745               268.9 ns/op            48 B/op          1 allocs/op
+
 PASS
 */
 func BenchmarkRlock(b *testing.B) {
@@ -234,3 +251,23 @@ func BenchmarkRlock(b *testing.B) {
                lock1.RLock()()
        }
 }
+
+/*
+goos: linux
+goarch: amd64
+pkg: github.com/qydysky/part/sync
+cpu: Intel(R) N100
+BenchmarkRlock1
+BenchmarkRlock1-4
+
+       7057746               158.2 ns/op             0 B/op          0 allocs/op
+
+PASS
+*/
+func BenchmarkRlock1(b *testing.B) {
+       var lock1 sync.RWMutex
+       for i := 0; i < b.N; i++ {
+               lock1.RLock()
+               lock1.RUnlock()
+       }
+}