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  }