semaphore_grant.h raw

   1  // Copyright (c) 2009-2010 Satoshi Nakamoto
   2  // Copyright (c) 2009-present The Bitcoin Core developers
   3  // Distributed under the MIT software license, see the accompanying
   4  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
   5  
   6  #ifndef BITCOIN_SEMAPHORE_GRANT_H
   7  #define BITCOIN_SEMAPHORE_GRANT_H
   8  
   9  #include <semaphore>
  10  
  11  /** RAII-style semaphore lock */
  12  template <std::ptrdiff_t LeastMaxValue = std::counting_semaphore<>::max()>
  13  class CountingSemaphoreGrant
  14  {
  15  private:
  16      std::counting_semaphore<LeastMaxValue>* sem;
  17      bool fHaveGrant;
  18  
  19  public:
  20      void Acquire() noexcept
  21      {
  22          if (fHaveGrant) {
  23              return;
  24          }
  25          sem->acquire();
  26          fHaveGrant = true;
  27      }
  28  
  29      void Release() noexcept
  30      {
  31          if (!fHaveGrant) {
  32              return;
  33          }
  34          sem->release();
  35          fHaveGrant = false;
  36      }
  37  
  38      bool TryAcquire() noexcept
  39      {
  40          if (!fHaveGrant && sem->try_acquire()) {
  41              fHaveGrant = true;
  42          }
  43          return fHaveGrant;
  44      }
  45  
  46      // Disallow copy.
  47      CountingSemaphoreGrant(const CountingSemaphoreGrant&) = delete;
  48      CountingSemaphoreGrant& operator=(const CountingSemaphoreGrant&) = delete;
  49  
  50      // Allow move.
  51      CountingSemaphoreGrant(CountingSemaphoreGrant&& other) noexcept
  52      {
  53          sem = other.sem;
  54          fHaveGrant = other.fHaveGrant;
  55          other.fHaveGrant = false;
  56          other.sem = nullptr;
  57      }
  58  
  59      CountingSemaphoreGrant& operator=(CountingSemaphoreGrant&& other) noexcept
  60      {
  61          Release();
  62          sem = other.sem;
  63          fHaveGrant = other.fHaveGrant;
  64          other.fHaveGrant = false;
  65          other.sem = nullptr;
  66          return *this;
  67      }
  68  
  69      CountingSemaphoreGrant() noexcept : sem(nullptr), fHaveGrant(false) {}
  70  
  71      explicit CountingSemaphoreGrant(std::counting_semaphore<LeastMaxValue>& sema, bool fTry = false) noexcept : sem(&sema), fHaveGrant(false)
  72      {
  73          if (fTry) {
  74              TryAcquire();
  75          } else {
  76              Acquire();
  77          }
  78      }
  79  
  80      ~CountingSemaphoreGrant()
  81      {
  82          Release();
  83      }
  84  
  85      explicit operator bool() const noexcept
  86      {
  87          return fHaveGrant;
  88      }
  89  };
  90  
  91  using BinarySemaphoreGrant = CountingSemaphoreGrant<1>;
  92  
  93  #endif // BITCOIN_SEMAPHORE_GRANT_H
  94