gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

mutex_safe.go (1161B)


      1 package mutexes
      2 
      3 import (
      4 	"sync/atomic"
      5 )
      6 
      7 // WithSafety wrapps the supplied Mutex to protect unlock fns
      8 // from being called multiple times
      9 func WithSafety(mu Mutex) Mutex {
     10 	return &safeMutex{mu: mu}
     11 }
     12 
     13 // WithSafetyRW wrapps the supplied RWMutex to protect unlock
     14 // fns from being called multiple times
     15 func WithSafetyRW(mu RWMutex) RWMutex {
     16 	return &safeRWMutex{mu: mu}
     17 }
     18 
     19 // safeMutex simply wraps a Mutex to add multi-unlock safety
     20 type safeMutex struct{ mu Mutex }
     21 
     22 func (mu *safeMutex) Lock() func() {
     23 	unlock := mu.mu.Lock()
     24 	return once(unlock)
     25 }
     26 
     27 // safeRWMutex simply wraps a RWMutex to add multi-unlock safety
     28 type safeRWMutex struct{ mu RWMutex }
     29 
     30 func (mu *safeRWMutex) Lock() func() {
     31 	unlock := mu.mu.Lock()
     32 	return once(unlock)
     33 }
     34 
     35 func (mu *safeRWMutex) RLock() func() {
     36 	unlock := mu.mu.RLock()
     37 	return once(unlock)
     38 }
     39 
     40 // once will perform 'do' only once, this is safe for unlocks
     41 // as 2 functions calling 'unlock()' don't need absolute guarantees
     42 // that by the time it is completed the unlock was finished.
     43 func once(do func()) func() {
     44 	var done uint32
     45 	return func() {
     46 		if atomic.CompareAndSwapUint32(&done, 0, 1) {
     47 			do()
     48 		}
     49 	}
     50 }