github.com/loov/combiner@v0.1.0/extcombiner/mutex.go (about) 1 package extcombiner 2 3 import ( 4 "runtime" 5 "sync" 6 "sync/atomic" 7 ) 8 9 // Mutex is a combiner queue that uses mutex to serialize operations. 10 // 11 // Not recommended, only for comparison. 12 type Mutex struct { 13 mu sync.Mutex 14 batcher Batcher 15 } 16 17 // NewMutex creates a combiner queue based on a mutex. 18 func NewMutex(batcher Batcher) *Mutex { 19 c := &Mutex{} 20 c.batcher = batcher 21 return c 22 } 23 24 // Do passes value to Batcher and waits for completion 25 func (c *Mutex) Do(v interface{}) { 26 c.mu.Lock() 27 c.batcher.Start() 28 c.batcher.Do(v) 29 c.batcher.Finish() 30 c.mu.Unlock() 31 } 32 33 // SpinMutex is a combiner queue that uses a spinning mutex to serialize operations. 34 // 35 // Not recommended, only for comparison. 36 type SpinMutex struct { 37 mu spinmutex 38 batcher Batcher 39 } 40 41 // NewSpinMutex creates a combiner queue based on a spin mutex. 42 func NewSpinMutex(batcher Batcher) *SpinMutex { 43 c := &SpinMutex{} 44 c.batcher = batcher 45 return c 46 } 47 48 // Do passes value to Batcher and waits for completion 49 func (c *SpinMutex) Do(v interface{}) { 50 c.mu.Lock() 51 c.batcher.Start() 52 c.batcher.Do(v) 53 c.batcher.Finish() 54 c.mu.Unlock() 55 } 56 57 type spinmutex struct { 58 locked int64 59 _ [7]int64 60 } 61 62 func (m *spinmutex) Lock() { 63 for atomic.SwapInt64(&m.locked, 1) == 1 { 64 for try := 0; atomic.LoadInt64(&m.locked) == 1; try++ { 65 if try > 256 { 66 runtime.Gosched() 67 } 68 } 69 } 70 } 71 72 func (m *spinmutex) Unlock() { 73 atomic.StoreInt64(&m.locked, 0) 74 }