func (s *Semaphore) IsEmpty() bool {
	return len(s.sem) == 0
}
IsEmpty will return true if no tickets are being held at that instant.
It is safe to call concurrently with Acquire and Release, though do note
that the result may then be unpredictable.
package semaphore
import (
	"errors"
	"time"
)
var ErrNoTickets = errors.New("could not acquire semaphore ticket")
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() {
	<-s.sem
}