gtsocial-umbx

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

mutex.go (2309B)


      1 package mutexes
      2 
      3 import (
      4 	"sync"
      5 )
      6 
      7 // Mutex defines a wrappable mutex. By forcing unlocks
      8 // via returned function it makes wrapping much easier
      9 type Mutex interface {
     10 	// Lock performs a mutex lock, returning an unlock function
     11 	Lock() (unlock func())
     12 }
     13 
     14 // RWMutex defines a wrappable read-write mutex. By forcing
     15 // unlocks via returned functions it makes wrapping much easier
     16 type RWMutex interface {
     17 	Mutex
     18 
     19 	// RLock performs a mutex read lock, returning an unlock function
     20 	RLock() (runlock func())
     21 }
     22 
     23 // New returns a new base Mutex implementation
     24 func New() Mutex {
     25 	return &baseMutex{}
     26 }
     27 
     28 // NewRW returns a new base RWMutex implementation
     29 func NewRW() RWMutex {
     30 	return &baseRWMutex{}
     31 }
     32 
     33 // WithFunc wraps the supplied Mutex to call the provided hooks on lock / unlock
     34 func WithFunc(mu Mutex, onLock, onUnlock func()) Mutex {
     35 	return &fnMutex{mu: mu, lo: onLock, un: onUnlock}
     36 }
     37 
     38 // WithFuncRW wrapps the supplied RWMutex to call the provided hooks on lock / rlock / unlock/ runlock
     39 func WithFuncRW(mu RWMutex, onLock, onRLock, onUnlock, onRUnlock func()) RWMutex {
     40 	return &fnRWMutex{mu: mu, lo: onLock, rlo: onRLock, un: onUnlock, run: onRUnlock}
     41 }
     42 
     43 // baseMutex simply wraps a sync.Mutex to implement our Mutex interface
     44 type baseMutex sync.Mutex
     45 
     46 func (mu *baseMutex) Lock() func() {
     47 	(*sync.Mutex)(mu).Lock()
     48 	return (*sync.Mutex)(mu).Unlock
     49 }
     50 
     51 // baseRWMutex simply wraps a sync.RWMutex to implement our RWMutex interface
     52 type baseRWMutex sync.RWMutex
     53 
     54 func (mu *baseRWMutex) Lock() func() {
     55 	(*sync.RWMutex)(mu).Lock()
     56 	return (*sync.RWMutex)(mu).Unlock
     57 }
     58 
     59 func (mu *baseRWMutex) RLock() func() {
     60 	(*sync.RWMutex)(mu).RLock()
     61 	return (*sync.RWMutex)(mu).RUnlock
     62 }
     63 
     64 // fnMutex wraps a Mutex to add hooks for Lock and Unlock
     65 type fnMutex struct {
     66 	mu Mutex
     67 	lo func()
     68 	un func()
     69 }
     70 
     71 func (mu *fnMutex) Lock() func() {
     72 	unlock := mu.mu.Lock()
     73 	mu.lo()
     74 	return func() {
     75 		mu.un()
     76 		unlock()
     77 	}
     78 }
     79 
     80 // fnRWMutex wraps a RWMutex to add hooks for Lock, RLock, Unlock and RUnlock
     81 type fnRWMutex struct {
     82 	mu  RWMutex
     83 	lo  func()
     84 	rlo func()
     85 	un  func()
     86 	run func()
     87 }
     88 
     89 func (mu *fnRWMutex) Lock() func() {
     90 	unlock := mu.mu.Lock()
     91 	mu.lo()
     92 	return func() {
     93 		mu.un()
     94 		unlock()
     95 	}
     96 }
     97 
     98 func (mu *fnRWMutex) RLock() func() {
     99 	unlock := mu.mu.RLock()
    100 	mu.rlo()
    101 	return func() {
    102 		mu.run()
    103 		unlock()
    104 	}
    105 }