PLCnext API Documentation 25.0.2.69
ConditionVariable.hpp
1
2//
3// Copyright Phoenix Contact GmbH & Co. KG
4//
6#pragma once
8#include "Arp/System/Commons/Threading/Mutex.hpp"
9#include "Arp/System/Commons/Chrono/TimePoint.hpp"
10
11// forwards
12namespace Arp::System::Ve
13{
14class ICondVariableService;
15}
16
18{
19
20using namespace Arp::System::Commons::Chrono;
21
27{
28public: // construction/destruction
31
34
35public: // operations
36
52 template<class Predicate>
53 void Wait(Mutex& mutex, Predicate predicate);
54
61 template<class Predicate>
62 bool WaitFor(Mutex& mutex, uint64 timeoutMs, Predicate predicate);
63
70 template<class Predicate>
71 bool WaitUntil(Mutex& mutex, TimePointClockSteady timePoint, Predicate predicate);
72
74 void NotifyOne(void);
75
77 void NotifyAll(void);
78
79private: // methods
80 void WaitInternal(Mutex& mutex);
81 bool WaitUntilInternal(Mutex& mutex, TimePointClockSteady timePoint);
82
83 static SteadyTimePoint CalculateWaitForTimepoint(uint64 timeoutMs);
84 static TimePointClockSteady RoundUpToMultipleOf(const TimePointClockSteady& timePoint, const ClockSteady::duration& intervalRounding);
85 static ClockSteady::duration RoundUpToMultipleOf(const ClockSteady::duration& duration, const ClockSteady::duration& intervalRounding);
86 static ClockSteady::duration RoundDownToMultipleOf(const ClockSteady::duration& duration, const Arp::uint64& intervalRounding);
87
88private: // deleted methods
90 ConditionVariable(const ConditionVariable& arg) = delete;
91
93 ConditionVariable& operator=(const ConditionVariable& arg) = delete;
94
95private: // fields
96 Arp::System::Ve::ICondVariableService *pCondVariableService;
97};
98
100// inline methods of class ConditionVariable
101template<class Predicate>
102void ConditionVariable::Wait(Mutex& mutex, Predicate predicate)
103{
104 while (!predicate())
105 {
106 WaitInternal(mutex);
107 }
108}
109
110template<class Predicate>
111bool ConditionVariable::WaitFor(Mutex& mutex, uint64 timeoutMs, Predicate predicate)
112{
113 SteadyTimePoint timePoint = CalculateWaitForTimepoint(timeoutMs);
114 return WaitUntil(mutex, timePoint, predicate);
115}
116
117template<class Predicate>
118bool ConditionVariable::WaitUntil(Mutex& mutex, TimePointClockSteady timePoint, Predicate predicate)
119{
120 bool result = true;
121 while ((!predicate()) && result)
122 {
123 result = WaitUntilInternal(mutex, timePoint);
124 }
125
126 // https://www.man7.org/linux/man-pages/man3/pthread_cond_timedwait.3p.html
127 // Condition Wait Semantics
128 // Similarly, when
129 // pthread_cond_timedwait() returns with the timeout error, the
130 // associated predicate may be true due to an unavoidable race
131 // between the expiration of the timeout and the predicate state
132 // change.
133 return predicate();
134}
135
136} // end of namespace Arp::System::Commons::Threading
Condition variables can be used to synchronize between multiple threads
Definition: ConditionVariable.hpp:27
void NotifyOne(void)
Unblocks at least one thread waiting on this condition variable.
Definition: ConditionVariable.cpp:38
~ConditionVariable(void)
Destructs this instance and frees all resources.
Definition: ConditionVariable.cpp:25
void NotifyAll(void)
Unblocks every thread waiting on this condition variable.
Definition: ConditionVariable.cpp:43
bool WaitFor(Mutex &mutex, uint64 timeoutMs, Predicate predicate)
Like Wait but returns if the signal is not deliverd within a specified time
Definition: ConditionVariable.hpp:111
void Wait(Mutex &mutex, Predicate predicate)
Blocks the calling thread until NotifyOne or NotifyAll is invoked and the predicate is fullfilled
Definition: ConditionVariable.hpp:102
ConditionVariable(void)
Constructs an ConditionVariable instance.
Definition: ConditionVariable.cpp:14
bool WaitUntil(Mutex &mutex, TimePointClockSteady timePoint, Predicate predicate)
Like Wait but returns if the signal is not deliverd until a specified time point
Definition: ConditionVariable.hpp:118
Mutual exclusion object to prevent data from concurrent modifications.
Definition: Mutex.hpp:27
SteadyClock::time_point SteadyTimePoint
Represents the type of a monotonic clock time-point.
Definition: ChronoTypes.hpp:31
std::uint64_t uint64
The Arp unsigned integer type of 8 byte size.
Definition: PrimitiveTypes.hpp:37
Namespace for time related classes
Namespace for classes handling threads and synchronization