github.com/teng231/glock@v1.1.11/kmutex.go (about) 1 package glock 2 3 import "sync" 4 5 type IKmutex interface { 6 Lock(key interface{}) 7 Unlock(key interface{}) 8 } 9 10 // Kmutex Can be locked by unique ID 11 type Kmutex struct { 12 c *sync.Cond 13 l sync.Locker 14 s map[interface{}]struct{} 15 } 16 17 // CreateKmutexInstance new Kmutex 18 func CreateKmutexInstance() *Kmutex { 19 l := sync.Mutex{} 20 return &Kmutex{c: sync.NewCond(&l), l: &l, s: make(map[interface{}]struct{})} 21 } 22 23 // WithLock Create new Kmutex with user provided lock 24 func WithLock(l sync.Locker) *Kmutex { 25 return &Kmutex{c: sync.NewCond(l), l: l, s: make(map[interface{}]struct{})} 26 } 27 28 func (km *Kmutex) locked(key interface{}) (ok bool) { _, ok = km.s[key]; return } 29 30 // Unlock Kmutex by unique ID 31 func (km *Kmutex) Unlock(key interface{}) { 32 km.l.Lock() 33 defer km.l.Unlock() 34 delete(km.s, key) 35 km.c.Broadcast() 36 } 37 38 // Lock Kmutex by unique ID 39 func (km *Kmutex) Lock(key interface{}) { 40 km.l.Lock() 41 defer km.l.Unlock() 42 for km.locked(key) { 43 km.c.Wait() 44 } 45 km.s[key] = struct{}{} 46 } 47 48 // satisfy sync.Locker interface 49 type locker struct { 50 km *Kmutex 51 key interface{} 52 } 53 54 // Lock locks m. If the lock is already in use, the calling goroutine blocks until the mutex is available. 55 func (l locker) Lock() { 56 l.km.Lock(l.key) 57 } 58 59 // Unlock unlocks m. It is a run-time error if m is not locked on entry to Unlock. 60 func (l locker) Unlock() { 61 l.km.Unlock(l.key) 62 } 63 64 // Locker Return a object which implement sync.Locker interface 65 // A Locker represents an object that can be locked and unlocked. 66 func (km Kmutex) Locker(key interface{}) sync.Locker { 67 return locker{ 68 key: key, 69 km: &km, 70 } 71 }