Skip to content

Commit 263fa98

Browse files
committed
Introduce WaitGroup and StoppableWaitGroup
1 parent 69d2a04 commit 263fa98

File tree

3 files changed

+92
-0
lines changed

3 files changed

+92
-0
lines changed

lib/base/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ set(base_SOURCES
8787
unixsocket.cpp unixsocket.hpp
8888
utility.cpp utility.hpp
8989
value.cpp value.hpp value-operators.cpp
90+
wait-group.cpp wait-group.hpp
9091
win32.hpp
9192
workqueue.cpp workqueue.hpp
9293
)

lib/base/wait-group.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/* Icinga 2 | (c) 2025 Icinga GmbH | GPLv2+ */
2+
3+
#include "base/wait-group.hpp"
4+
5+
using namespace icinga;
6+
7+
bool StoppableWaitGroup::try_lock_shared()
8+
{
9+
std::unique_lock lock (m_Mutex);
10+
11+
if (m_Stopped) {
12+
return false;
13+
}
14+
15+
++m_SharedLocks;
16+
return true;
17+
}
18+
19+
void StoppableWaitGroup::unlock_shared()
20+
{
21+
std::unique_lock lock (m_Mutex);
22+
23+
if (!--m_SharedLocks && m_Stopped) {
24+
m_CV.notify_all();
25+
}
26+
}
27+
28+
/**
29+
* Disallow new shared locks, wait for all existing ones.
30+
*/
31+
void StoppableWaitGroup::Join()
32+
{
33+
std::unique_lock lock (m_Mutex);
34+
35+
m_Stopped = true;
36+
m_CV.wait(lock, [this] { return !m_SharedLocks; });
37+
}

lib/base/wait-group.hpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/* Icinga 2 | (c) 2025 Icinga GmbH | GPLv2+ */
2+
3+
#pragma once
4+
5+
#include "base/object.hpp"
6+
#include <condition_variable>
7+
#include <cstdint>
8+
#include <mutex>
9+
10+
namespace icinga
11+
{
12+
13+
/**
14+
* A synchronization interface that allows concurrent shared locking.
15+
*
16+
* @ingroup base
17+
*/
18+
class WaitGroup : public Object
19+
{
20+
public:
21+
DECLARE_PTR_TYPEDEFS(WaitGroup);
22+
23+
virtual bool try_lock_shared() = 0;
24+
virtual void unlock_shared() = 0;
25+
};
26+
27+
/**
28+
* A thread-safe wait group that can be stopped to prevent further shared locking.
29+
*
30+
* @ingroup base
31+
*/
32+
class StoppableWaitGroup : public WaitGroup
33+
{
34+
public:
35+
DECLARE_PTR_TYPEDEFS(StoppableWaitGroup);
36+
37+
StoppableWaitGroup() = default;
38+
StoppableWaitGroup(const StoppableWaitGroup&) = delete;
39+
StoppableWaitGroup(StoppableWaitGroup&&) = delete;
40+
StoppableWaitGroup& operator=(const StoppableWaitGroup&) = delete;
41+
StoppableWaitGroup& operator=(StoppableWaitGroup&&) = delete;
42+
43+
bool try_lock_shared() override;
44+
void unlock_shared() override;
45+
void Join();
46+
47+
private:
48+
std::mutex m_Mutex;
49+
std::condition_variable m_CV;
50+
uint_fast32_t m_SharedLocks = 0;
51+
bool m_Stopped = false;
52+
};
53+
54+
}

0 commit comments

Comments
 (0)