-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathEvent.h
111 lines (86 loc) · 2.9 KB
/
Event.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
//
// <author> damirlj@yahoo.com
// Copyright (c) 2023. All rights reserved!
//
#ifndef EVENT_H
#define EVENT_H
// std library
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <functional> // std::invoke
#include <vector>
#include <thread>
namespace utils
{
/**
* Implementation of the event synchronization primitive.
* Will synchronize threads, one producer: signaling the event to single, or
* all consumer threads waiting on the same condition
*/
class Event final
{
public:
using event_wait_t = enum class EEvent : std::uint8_t { timeout = 0, signaled };
using waiting_threads_t = std::vector<std::thread::id>;
/**
* C-tor
*
* @param autoReset In case that is set to true, will reset the event after being signaled
* at consumer point, so that it can wait - block on the same event on the next recall
*/
explicit Event(bool autoReset) noexcept;
~Event();
// Copy functions forbidden
Event(const Event&) = delete;
Event& operator=(const Event&) = delete;
// Move operations forbidden
Event(Event&&) = delete;
Event& operator=(Event&&) = delete;
/**
* Wait on the event being signaled, or timeout expired
*
* @param timeout Timeout in milliseconds to wait
* @return Indication of the operation outcome {@link Event#event_wait_t}
*/
event_wait_t wait_for(std::chrono::milliseconds timeout);
/**
* Wait infinitely on event being signaled
*/
void wait();
/**
* Notify - wake up the single thread
*/
void notify();
/**
* Notify - wake up the all waiting threads
*
* @note If the event is auto reset - this will notify only the first
* woken thread
*/
void broadcast();
/**
* Manually reset event - in case of the auto reset is false.
*/
[[maybe_unused]] void reset();
private:
using notify_f = void (std::condition_variable::*)(void);
void setEvent(notify_f notifier)
{
std::lock_guard lock{m_lock};
m_predicate = true;
// There is at least one consumer-thread - waiting on the event to be signaled
if (not m_waitingThreads.empty())
{
std::invoke(notifier, m_event);
}
}
private:
std::condition_variable m_event; // not copyable nor movable
std::mutex m_lock; // not copyable nor movable
const bool m_autoReset;
bool m_predicate = false;
waiting_threads_t m_waitingThreads;
};
} // namespace utils
#endif // EVENT_H