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