aboutsummaryrefslogtreecommitdiff
path: root/src/sync.h
diff options
context:
space:
mode:
authorPieter Wuille <pieter@wuille.net>2023-08-21 18:14:52 -0400
committerPieter Wuille <pieter@wuille.net>2023-10-02 18:11:11 -0400
commit4d265d0342ae7e92df07ba51e8355db57c44f811 (patch)
treebf7a39144549b675da278630417c673c38fac7d6 /src/sync.h
parentc73cd423636e06df46742f573640ca773b281ffc (diff)
sync: modernize CSemaphore / CSemaphoreGrant
Diffstat (limited to 'src/sync.h')
-rw-r--r--src/sync.h73
1 files changed, 52 insertions, 21 deletions
diff --git a/src/sync.h b/src/sync.h
index 7242a793ab..45d40b5fdc 100644
--- a/src/sync.h
+++ b/src/sync.h
@@ -301,6 +301,10 @@ inline MutexType* MaybeCheckNotHeld(MutexType* m) LOCKS_EXCLUDED(m) LOCK_RETURNE
//! gcc and the -Wreturn-stack-address flag in clang, both enabled by default.
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
+/** An implementation of a semaphore.
+ *
+ * See https://en.wikipedia.org/wiki/Semaphore_(programming)
+ */
class CSemaphore
{
private:
@@ -309,25 +313,33 @@ private:
int value;
public:
- explicit CSemaphore(int init) : value(init) {}
+ explicit CSemaphore(int init) noexcept : value(init) {}
- void wait()
+ // Disallow default construct, copy, move.
+ CSemaphore() = delete;
+ CSemaphore(const CSemaphore&) = delete;
+ CSemaphore(CSemaphore&&) = delete;
+ CSemaphore& operator=(const CSemaphore&) = delete;
+ CSemaphore& operator=(CSemaphore&&) = delete;
+
+ void wait() noexcept
{
std::unique_lock<std::mutex> lock(mutex);
condition.wait(lock, [&]() { return value >= 1; });
value--;
}
- bool try_wait()
+ bool try_wait() noexcept
{
std::lock_guard<std::mutex> lock(mutex);
- if (value < 1)
+ if (value < 1) {
return false;
+ }
value--;
return true;
}
- void post()
+ void post() noexcept
{
{
std::lock_guard<std::mutex> lock(mutex);
@@ -345,45 +357,64 @@ private:
bool fHaveGrant;
public:
- void Acquire()
+ void Acquire() noexcept
{
- if (fHaveGrant)
+ if (fHaveGrant) {
return;
+ }
sem->wait();
fHaveGrant = true;
}
- void Release()
+ void Release() noexcept
{
- if (!fHaveGrant)
+ if (!fHaveGrant) {
return;
+ }
sem->post();
fHaveGrant = false;
}
- bool TryAcquire()
+ bool TryAcquire() noexcept
{
- if (!fHaveGrant && sem->try_wait())
+ if (!fHaveGrant && sem->try_wait()) {
fHaveGrant = true;
+ }
return fHaveGrant;
}
- void MoveTo(CSemaphoreGrant& grant)
+ // Disallow copy.
+ CSemaphoreGrant(const CSemaphoreGrant&) = delete;
+ CSemaphoreGrant& operator=(const CSemaphoreGrant&) = delete;
+
+ // Allow move.
+ CSemaphoreGrant(CSemaphoreGrant&& other) noexcept
+ {
+ sem = other.sem;
+ fHaveGrant = other.fHaveGrant;
+ other.fHaveGrant = false;
+ other.sem = nullptr;
+ }
+
+ CSemaphoreGrant& operator=(CSemaphoreGrant&& other) noexcept
{
- grant.Release();
- grant.sem = sem;
- grant.fHaveGrant = fHaveGrant;
- fHaveGrant = false;
+ Release();
+ sem = other.sem;
+ fHaveGrant = other.fHaveGrant;
+ other.fHaveGrant = false;
+ other.sem = nullptr;
+ return *this;
}
- CSemaphoreGrant() : sem(nullptr), fHaveGrant(false) {}
+ CSemaphoreGrant() noexcept : sem(nullptr), fHaveGrant(false) {}
- explicit CSemaphoreGrant(CSemaphore& sema, bool fTry = false) : sem(&sema), fHaveGrant(false)
+ explicit CSemaphoreGrant(CSemaphore& sema, bool fTry = false) noexcept : sem(&sema), fHaveGrant(false)
{
- if (fTry)
+ if (fTry) {
TryAcquire();
- else
+ } else {
Acquire();
+ }
}
~CSemaphoreGrant()
@@ -391,7 +422,7 @@ public:
Release();
}
- operator bool() const
+ explicit operator bool() const noexcept
{
return fHaveGrant;
}