From cfd83425b68d40c7a2229fee3831a496783585d6 Mon Sep 17 00:00:00 2001 From: Tamer Tas Date: Wed, 23 Dec 2015 15:45:48 +0200 Subject: [PATCH] Add semaphore pattern --- semaphore.go | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 semaphore.go diff --git a/semaphore.go b/semaphore.go new file mode 100644 index 0000000..766e76f --- /dev/null +++ b/semaphore.go @@ -0,0 +1,46 @@ +package semaphore + +import ( + "errors" + "time" +) + +var ( + ErrNoTickets = errors.New("semaphore: could not aquire semaphore") + ErrIllegalRelease = errors.New("semaphore: can't release the semaphore without acquiring it first") +) + +type Interface interface { + Acquire() error + Release() error +} + +type semaphore struct { + sem chan struct{} + timeout time.Duration +} + +func New(tickets int, timeout time.Duration) Semaphore { + return &semaphore{ + sem: make(chan struct{}, tickets), + timeout: timeout, + } +} + +func (s *semaphore) Acquire() error { + select { + case s.sem <- struct{}{}: + return nil + case <-time.After(s.timeout): + return ErrNoTickets + } +} + +func (s *semaphore) Release() error { + _, ok := <-s.sem + if !ok { + return ErrIllegalRelease + } + + return nil +}