/ src / semaphore_grant.h
semaphore_grant.h
 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