You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

semaphore.go 1.3 kB

4 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. // 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. package internal
  7. import (
  8. "context"
  9. "errors"
  10. )
  11. // NewSemaphore creates a new semaphore.
  12. func NewSemaphore(slots uint64) *Semaphore {
  13. ch := make(chan struct{}, slots)
  14. for i := uint64(0); i < slots; i++ {
  15. ch <- struct{}{}
  16. }
  17. return &Semaphore{
  18. permits: ch,
  19. }
  20. }
  21. // Semaphore is a synchronization primitive that controls access
  22. // to a common resource.
  23. type Semaphore struct {
  24. permits chan struct{}
  25. }
  26. // Len gets the number of permits available.
  27. func (s *Semaphore) Len() uint64 {
  28. return uint64(len(s.permits))
  29. }
  30. // Wait waits until a resource is available or until the context
  31. // is done.
  32. func (s *Semaphore) Wait(ctx context.Context) error {
  33. select {
  34. case <-s.permits:
  35. return nil
  36. case <-ctx.Done():
  37. return ctx.Err()
  38. }
  39. }
  40. // Release releases a resource back into the pool.
  41. func (s *Semaphore) Release() error {
  42. select {
  43. case s.permits <- struct{}{}:
  44. default:
  45. return errors.New("internal.Semaphore.Release: attempt to release more resources than are available")
  46. }
  47. return nil
  48. }