From c68694163b20b475710d0c1b61d8ae3a79a992fd Mon Sep 17 00:00:00 2001 From: Rainer Kartmann <rainer.kartmann@kit.edu> Date: Mon, 7 Dec 2020 14:18:01 +0100 Subject: [PATCH] Add CountingSemaphore --- SimoxUtility/CMakeLists.txt | 2 + SimoxUtility/threads.h | 1 + SimoxUtility/threads/CountingSemaphore.cpp | 42 +++++++++++++++ SimoxUtility/threads/CountingSemaphore.h | 61 ++++++++++++++++++++++ 4 files changed, 106 insertions(+) create mode 100644 SimoxUtility/threads/CountingSemaphore.cpp create mode 100644 SimoxUtility/threads/CountingSemaphore.h diff --git a/SimoxUtility/CMakeLists.txt b/SimoxUtility/CMakeLists.txt index 02e16fe9d..2745556a2 100644 --- a/SimoxUtility/CMakeLists.txt +++ b/SimoxUtility/CMakeLists.txt @@ -88,6 +88,7 @@ SET(SOURCES shapes/json_conversions.cpp threads/system_thread_id.cpp + threads/CountingSemaphore.cpp ) SET(INCLUDES @@ -256,6 +257,7 @@ SET(INCLUDES backport/span/gcc_header.h threads/system_thread_id.h + threads/CountingSemaphore.h ) simox_generate_subdir_headers( diff --git a/SimoxUtility/threads.h b/SimoxUtility/threads.h index cd685bff0..7c9962102 100644 --- a/SimoxUtility/threads.h +++ b/SimoxUtility/threads.h @@ -2,4 +2,5 @@ // This file is generated! +#include "threads/CountingSemaphore.h" #include "threads/system_thread_id.h" diff --git a/SimoxUtility/threads/CountingSemaphore.cpp b/SimoxUtility/threads/CountingSemaphore.cpp new file mode 100644 index 000000000..9e6687e62 --- /dev/null +++ b/SimoxUtility/threads/CountingSemaphore.cpp @@ -0,0 +1,42 @@ +#include "CountingSemaphore.h" + + +namespace simox::threads +{ + + CountingSemaphore::CountingSemaphore() + {} + + CountingSemaphore::CountingSemaphore(unsigned int count) : _count(count) + {} + + + void CountingSemaphore::notify() + { + std::lock_guard<std::mutex> lock(_mutex); + ++_count; + _condition.notify_one(); + } + + void CountingSemaphore::wait() + { + std::unique_lock<std::mutex> lock(_mutex); + _condition.wait(lock, [this]() + { + return _count > 0; + }); + --_count; + } + + bool CountingSemaphore::try_wait() + { + std::unique_lock<std::mutex> lock(_mutex); + if (_count > 0) + { + --_count; + return true; + } + return false; + } + +} diff --git a/SimoxUtility/threads/CountingSemaphore.h b/SimoxUtility/threads/CountingSemaphore.h new file mode 100644 index 000000000..a7bc78f90 --- /dev/null +++ b/SimoxUtility/threads/CountingSemaphore.h @@ -0,0 +1,61 @@ +#pragma once + +#include <condition_variable> +#include <mutex> + + +namespace simox::threads +{ + + /** + * @brief A counting semaphore. + * + * Threads can enter when the internal count is > 0. + * Notifiying the semaphore increments the count and allows threads to enter. + * A thread can wait until it may enter. When it enters, it decrements + * the internal count. + * + * Can be used e.g. in a Producer-Consumer pattern. + * The producer signals new jobs via `notify()`, while the consumer waits + * for new jobs via `wait()`. + */ + class CountingSemaphore + { + public: + + /// Construct an initially blocking semaphore (initial count 0). + CountingSemaphore(); + /// Construct a semaphore with the given count. + CountingSemaphore(unsigned int count); + + /** + * @brief Signal that one waiting thread may continue. + * Also known as `post()` or `signal()`. + */ + void notify(); + + /** + * @brief Wait until a thread may enter. + */ + void wait(); + + /** + * @brief Try to enter. If the semaphore is currently blocking, return false. + * @return True if entering was successful, false if semaphore was blocking. + */ + bool try_wait(); + + + private: + + /// The mutex for _condition and _count. + std::mutex _mutex; + /// The condition variable to wake up waking threads. + std::condition_variable _condition; + + /// The current count. Waiting threads may enter when > 0. + unsigned int _count = 0; + + }; + +} -- GitLab