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  }