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