PLCnext API Documentation 24.6.0.58
ConditionVariable.hpp
1
2//
3// Copyright PHOENIX CONTACT Electronics GmbH
4//
6#pragma once
8#include "Arp/System/Commons/Threading/Mutex.hpp"
9#include "Arp/System/Commons/Chrono/TimePoint.hpp"
10
11namespace Arp { namespace System { namespace Ve
12{
13class ICondVariableService;
14}}};
15
16namespace Arp { namespace System { namespace Commons { namespace Threading
17{
18
19using namespace Arp::System::Commons::Chrono;
20
26{
27public: // construction/destruction
30
33
34public: // operations
35
51 template<class Predicate>
52 void Wait(Mutex& mutex, Predicate predicate);
53
60 template<class Predicate>
61 bool WaitFor(Mutex& mutex, unsigned long timeoutMs, Predicate predicate);
62
69 template<class Predicate>
70 bool WaitUntil(Mutex& mutex, TimePointClockSteady timePoint, Predicate predicate);
71
73 void NotifyOne(void);
74
76 void NotifyAll(void);
77
78private: // methods
79 void WaitInternal(Mutex& mutex);
80 bool WaitUntilInternal(Mutex& mutex, TimePointClockSteady timePoint);
81
82private: // deleted methods
84 ConditionVariable(const ConditionVariable& arg) = delete;
85
87 ConditionVariable& operator=(const ConditionVariable& arg) = delete;
88
89private: // fields
90 Arp::System::Ve::ICondVariableService *pCondVariableService;
91};
92
94// inline methods of class ConditionVariable
95template<class Predicate>
96void ConditionVariable::Wait(Mutex& mutex, Predicate predicate)
97{
98 while (!predicate())
99 {
100 WaitInternal(mutex);
101 }
102}
103
104template<class Predicate>
105bool ConditionVariable::WaitFor(Mutex& mutex, unsigned long timeoutMs, Predicate predicate)
106{
107 SteadyTimePoint now = SteadyClock::now();
108 SteadyTimePoint timePoint = now + Milliseconds(timeoutMs);
109
110 return WaitUntil(mutex, timePoint, predicate);
111}
112
113template<class Predicate>
114bool ConditionVariable::WaitUntil(Mutex& mutex, TimePointClockSteady timePoint, Predicate predicate)
115{
116 bool result = true;
117 while ((!predicate()) && result)
118 {
119 result = WaitUntilInternal(mutex, timePoint);
120 }
121
122 // https://www.man7.org/linux/man-pages/man3/pthread_cond_timedwait.3p.html
123 // Condition Wait Semantics
124 // Similarly, when
125 // pthread_cond_timedwait() returns with the timeout error, the
126 // associated predicate may be true due to an unavoidable race
127 // between the expiration of the timeoutand the predicate state
128 // change.
129 return predicate();
130}
131
132}}}} // end of namespace Arp::System::Commons::Threading
Condition variables can be used to synchronize between multiple threads
Definition: ConditionVariable.hpp:26
void NotifyOne(void)
Unblocks at least one thread waiting on this condition variable.
~ConditionVariable(void)
Destructs this instance and frees all resources.
void NotifyAll(void)
Unblocks every thread waiting on this condition variable.
void Wait(Mutex &mutex, Predicate predicate)
Blocks the calling thread until NotifyOne or NotifyAll is invoked and the predicate is fullfilled
Definition: ConditionVariable.hpp:96
bool WaitFor(Mutex &mutex, unsigned long timeoutMs, Predicate predicate)
Like Wait but returns if the signal is not deliverd within a specified time
Definition: ConditionVariable.hpp:105
ConditionVariable(void)
Constructs an ConditionVariable instance.
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:114
Mutual exclusion object to prevent data from concurrent modifications.
Definition: Mutex.hpp:26
std::chrono::milliseconds Milliseconds
The Arp Milliseconds unit class.
Definition: TypeSystem.h:52
SteadyClock::time_point SteadyTimePoint
Represents the type of a monotonic clock timepoint.
Definition: TypeSystem.h:40
@ System
System components used by the System, Device, Plc or Io domains.
Namespace for time related classes
Definition: Clock.hpp:11
Root namespace for the PLCnext API