Files
Erik Fröjdh 5ee7844b35
Build and Deploy on local RHEL9 / build (push) Successful in 2m1s
Build on RHEL9 docker image / build (push) Successful in 3m59s
Build and Deploy on local RHEL8 / build (push) Successful in 5m10s
Build on RHEL8 docker image / build (push) Successful in 5m11s
Run Simulator Tests on local RHEL9 / build (push) Successful in 20m41s
Run Simulator Tests on local RHEL8 / build (push) Successful in 24m6s
dev/ Replaced sem_t with a C++20 like counting_semaphore (#1587)
* added C++17 backport of std::counting_semaphore

sls::counting_semaphore and sls::binary_semaphore mirror the C++20
<semaphore> types and are built on std::mutex and
std::condition_variable. Unnamed POSIX semaphores (sem_init) are not
implemented on macOS.
2026-10-26 18:03:13 +01:00

81 lines
2.4 KiB
C++

// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
#pragma once
/**
* @file counting_semaphore.h
* @short C++17 backport of std::counting_semaphore and std::binary_semaphore
*
* Mirrors the C++20 <semaphore> types so that the project can switch by
* replacing this include with <semaphore> and sls:: with std::. Unnamed POSIX
* semaphores (sem_init) cannot be used instead as they are not implemented on
* macOS.
*
* Differences to the std types:
* - try_acquire_for and try_acquire_until are not implemented
* - the constructor is not constexpr
* - try_acquire never fails spuriously (std allows it to)
* - the preconditions (0 <= desired <= max() and
* 0 <= update <= max() - counter) are not checked, as in std violating
* them is undefined behaviour
*
* Built on std::mutex and std::condition_variable, therefore NOT
* async-signal-safe. Do not call release() from a signal handler.
*/
#include <condition_variable>
#include <cstddef>
#include <limits>
#include <mutex>
namespace sls {
template <std::ptrdiff_t LeastMaxValue =
std::numeric_limits<std::ptrdiff_t>::max()>
class counting_semaphore {
static_assert(LeastMaxValue >= 0, "LeastMaxValue must be non-negative");
public:
static constexpr std::ptrdiff_t max() noexcept { return LeastMaxValue; }
explicit counting_semaphore(std::ptrdiff_t desired) : count_(desired) {}
counting_semaphore(const counting_semaphore &) = delete;
counting_semaphore &operator=(const counting_semaphore &) = delete;
void acquire() {
std::unique_lock<std::mutex> lk(mtx_);
cv_.wait(lk, [this] { return count_ > 0; });
--count_;
}
bool try_acquire() noexcept {
std::lock_guard<std::mutex> lk(mtx_);
if (count_ == 0)
return false;
--count_;
return true;
}
void release(std::ptrdiff_t update = 1) {
// notify while holding the lock: a thread returning from acquire()
// may destroy the semaphore, which must not happen before we are done
// with the condition variable
std::lock_guard<std::mutex> lk(mtx_);
count_ += update;
if (update == 1)
cv_.notify_one();
else
cv_.notify_all();
}
private:
std::mutex mtx_;
std::condition_variable cv_;
std::ptrdiff_t count_;
};
using binary_semaphore = counting_semaphore<1>;
} // namespace sls