Introduce WaitGroup and StoppableWaitGroup

This commit is contained in:
Alexander A. Klimov 2025-05-22 17:11:23 +02:00
parent 69d2a0442a
commit 18fb93fc11
3 changed files with 93 additions and 0 deletions

View File

@ -87,6 +87,7 @@ set(base_SOURCES
unixsocket.cpp unixsocket.hpp
utility.cpp utility.hpp
value.cpp value.hpp value-operators.cpp
wait-group.cpp wait-group.hpp
win32.hpp
workqueue.cpp workqueue.hpp
)

38
lib/base/wait-group.cpp Normal file
View File

@ -0,0 +1,38 @@
/* Icinga 2 | (c) 2025 Icinga GmbH | GPLv2+ */
#include "base/wait-group.hpp"
using namespace icinga;
bool StoppableWaitGroup::try_lock_shared()
{
std::unique_lock lock (m_Mutex);
if (m_Stopped) {
return false;
}
++m_SharedLocks;
return true;
}
void StoppableWaitGroup::unlock_shared()
{
std::unique_lock lock (m_Mutex);
if (!--m_SharedLocks && m_Stopped) {
lock.unlock();
m_CV.notify_all();
}
}
/**
* Disallow new shared locks, wait for all existing ones.
*/
void StoppableWaitGroup::Join()
{
std::unique_lock lock (m_Mutex);
m_Stopped = true;
m_CV.wait(lock, [this] { return !m_SharedLocks; });
}

54
lib/base/wait-group.hpp Normal file
View File

@ -0,0 +1,54 @@
/* Icinga 2 | (c) 2025 Icinga GmbH | GPLv2+ */
#pragma once
#include "base/object.hpp"
#include <condition_variable>
#include <cstdint>
#include <mutex>
namespace icinga
{
/**
* A synchronization interface that allows concurrent shared locking.
*
* @ingroup base
*/
class WaitGroup : public Object
{
public:
DECLARE_PTR_TYPEDEFS(WaitGroup);
virtual bool try_lock_shared() = 0;
virtual void unlock_shared() = 0;
};
/**
* A thread-safe wait group that can be stopped to prevent further shared locking.
*
* @ingroup base
*/
class StoppableWaitGroup : public WaitGroup
{
public:
DECLARE_PTR_TYPEDEFS(StoppableWaitGroup);
StoppableWaitGroup() = default;
StoppableWaitGroup(const StoppableWaitGroup&) = delete;
StoppableWaitGroup(StoppableWaitGroup&&) = delete;
StoppableWaitGroup& operator=(const StoppableWaitGroup&) = delete;
StoppableWaitGroup& operator=(StoppableWaitGroup&&) = delete;
bool try_lock_shared() override;
void unlock_shared() override;
void Join();
private:
std::mutex m_Mutex;
std::condition_variable m_CV;
uint_fast32_t m_SharedLocks = 0;
bool m_Stopped = false;
};
}