blob: 792e531a525b0f0c300d4b510ec52379d2a3f1dd [file] [log] [blame]
Don Newton379ae252019-04-01 12:17:06 -04001// Copyright (C) MongoDB, Inc. 2017-present.
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may
4// not use this file except in compliance with the License. You may obtain
5// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
7package internal
8
9import (
10 "context"
11 "errors"
12)
13
14// NewSemaphore creates a new semaphore.
15func NewSemaphore(slots uint64) *Semaphore {
16 ch := make(chan struct{}, slots)
17 for i := uint64(0); i < slots; i++ {
18 ch <- struct{}{}
19 }
20
21 return &Semaphore{
22 permits: ch,
23 }
24}
25
26// Semaphore is a synchronization primitive that controls access
27// to a common resource.
28type Semaphore struct {
29 permits chan struct{}
30}
31
32// Len gets the number of permits available.
33func (s *Semaphore) Len() uint64 {
34 return uint64(len(s.permits))
35}
36
37// Wait waits until a resource is available or until the context
38// is done.
39func (s *Semaphore) Wait(ctx context.Context) error {
40 select {
41 case <-s.permits:
42 return nil
43 case <-ctx.Done():
44 return ctx.Err()
45 }
46}
47
48// Release releases a resource back into the pool.
49func (s *Semaphore) Release() error {
50 select {
51 case s.permits <- struct{}{}:
52 default:
53 return errors.New("internal.Semaphore.Release: attempt to release more resources than are available")
54 }
55
56 return nil
57}