github.com/insolar/vanilla@v0.0.0-20201023172447-248fdf805322/synckit/semaphore.go (about) 1 // Copyright 2020 Insolar Network Ltd. 2 // All rights reserved. 3 // This material is licensed under the Insolar License version 1.0, 4 // available at https://github.com/insolar/assured-ledger/blob/master/LICENSE.md. 5 6 package synckit 7 8 import ( 9 "time" 10 11 "github.com/insolar/vanilla/throw" 12 ) 13 14 func NewSemaphore(limit int) Semaphore { 15 if limit <= 0 { 16 panic(throw.IllegalValue()) 17 } 18 return Semaphore{make(chan struct{}, limit)} 19 } 20 21 type Semaphore struct { 22 sema chan struct{} 23 } 24 25 func (v Semaphore) Lock() { 26 v.sema <- struct{}{} 27 } 28 29 func (v Semaphore) TryLock() bool { 30 select { 31 case v.sema <- struct{}{}: 32 return true 33 default: 34 return false 35 } 36 } 37 38 func (v Semaphore) IsFull() bool { 39 return len(v.sema) == cap(v.sema) 40 } 41 42 func (v Semaphore) LockTimeout(d time.Duration) bool { 43 return v.LockExt(d, nil) 44 } 45 46 func (v Semaphore) LockExt(d time.Duration, done <-chan struct{}) bool { 47 select { 48 case v.sema <- struct{}{}: 49 return true 50 case <-done: 51 return false 52 default: 53 select { 54 case v.sema <- struct{}{}: 55 return true 56 case <-done: 57 return false 58 case <-time.After(d): 59 } 60 return false 61 } 62 } 63 64 func (v Semaphore) Unlock() { 65 <-v.sema 66 } 67 68 func (v Semaphore) Close() { 69 close(v.sema) 70 }