return
}
+func (t Action) Error() string {
+ return string(t)
+}
+
type Error struct {
- son error
Reason string
action Action
}
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)
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)
}
}
-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
+ },
}
}
}
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)
})
*/
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)
})
*/
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)
})
*/
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)
// 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()
}
}
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
})
}
}
}}
ul := l.RLock(time.Second, time.Second)
- ul(func() {
+ ul(func(ulocked bool) (doUlock bool) {
time.Sleep(time.Second * 2)
+ return true
})
}
}
}}
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()
}
ul1()
c <- 2
})
- ul(func() {
+ ul(func(ulocked bool) (doUlock bool) {
time.Sleep(time.Second)
+ return true
})
c <- 0
if <-c != 1 {
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()
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
})
}
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) {
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()
+ }
+}