Advertisement
Guest User

Untitled

a guest
Apr 26th, 2015
194
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 1.70 KB | None | 0 0
  1. // Package multilock provide A simple method to lock base on a holder
  2. package multilock
  3.  
  4. import (
  5. "errors"
  6. "sync"
  7. )
  8.  
  9. type refCounter struct {
  10. counter int
  11. lock sync.RWMutex
  12. }
  13. type lockMap map[interface{}]*refCounter
  14.  
  15. // MultiLock is the main interface for lock base on holder
  16. type MultiLock interface {
  17. // Lock base on the holder
  18. Lock(interface{})
  19.  
  20. // RLock lock the rw for reading
  21. RLock(interface{})
  22.  
  23. // Unlock the holder
  24. Unlock(interface{})
  25.  
  26. // RUnlock the the read lock
  27. RUnlock(interface{})
  28. }
  29.  
  30. // A multi lock type
  31. type lock struct {
  32. inUse lockMap
  33. l *sync.Mutex
  34. pool *sync.Pool
  35. }
  36.  
  37. func (l *lock) Lock(holder interface{}) {
  38. m := l.getLocker(holder)
  39. m.counter++
  40. m.lock.Lock()
  41. }
  42.  
  43. func (l *lock) RLock(holder interface{}) {
  44. m := l.getLocker(holder)
  45. m.counter++
  46. m.lock.RLock()
  47. }
  48.  
  49. func (l *lock) Unlock(holder interface{}) {
  50. m := l.getLocker(holder)
  51. m.lock.Unlock()
  52. l.putBackInPool(holder, m)
  53. }
  54.  
  55. func (l *lock) RUnlock(holder interface{}) {
  56. m := l.getLocker(holder)
  57. m.lock.RUnlock()
  58. l.putBackInPool(holder, m)
  59. }
  60.  
  61. func (l *lock) putBackInPool(holder interface{}, m *refCounter) {
  62. l.l.Lock()
  63. defer l.l.Unlock()
  64.  
  65. m.counter--
  66. if m.counter <= 0 {
  67. l.pool.Put(m)
  68. delete(l.inUse, holder)
  69. }
  70. }
  71.  
  72. func (l *lock) getLocker(holder interface{}) *refCounter {
  73. l.l.Lock()
  74. defer l.l.Unlock()
  75. res, ok := l.inUse[holder]
  76. if !ok {
  77. p := l.pool.Get()
  78. res, ok = p.(*refCounter)
  79. if !ok {
  80. panic(errors.New("the pool return invalid result"))
  81. }
  82.  
  83. l.inUse[holder] = res
  84. }
  85. return res
  86. }
  87.  
  88. // NewMultiLock create a new multi lock
  89. func NewMultiLock() MultiLock {
  90. return &lock{
  91. make(lockMap),
  92. &sync.Mutex{},
  93. &sync.Pool{
  94. New: func() interface{} {
  95. return &refCounter{0, sync.RWMutex{}}
  96. },
  97. },
  98. }
  99. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement