ORIGINAL
Loading...
Searching...
No Matches
condition.h
Go to the documentation of this file.
1#ifndef CONDITION_H
2#define CONDITION_H
3#include "mutex.h"
4#include "zeit.h"
5
23namespace original
24{
38 {
39 public:
41 explicit conditionBase() = default;
42
49 virtual void wait(mutexBase& mutex) = 0;
50
59 virtual bool waitFor(mutexBase& mutex, time::duration d) = 0;
60
69 template<typename Pred>
70 void wait(mutexBase& mutex, Pred predicate) noexcept(noexcept(predicate()));
71
81 template<typename Pred>
82 bool waitFor(mutexBase& mutex, const time::duration& d, Pred predicate) noexcept(noexcept(predicate()));
83
88 virtual void notify() = 0;
89
94 virtual void notifyAll() = 0;
95
97 virtual ~conditionBase() = default;
98
100 conditionBase(const conditionBase&) = delete;
101
104 };
105
113 class pCondition final : public conditionBase
114 {
115 pthread_cond_t cond_;
116
117 public:
118 // Inherit template methods from conditionBase
121
126 explicit pCondition();
127
134 void wait(mutexBase& mutex) override;
135
144 bool waitFor(mutexBase& mutex, time::duration d) override;
145
150 void notify() override;
151
156 void notifyAll() override;
157
162 ~pCondition() override;
163 };
164}
165
166template<typename Pred>
167void original::conditionBase::wait(mutexBase& mutex, Pred predicate) noexcept(noexcept(predicate())) {
168 while (!predicate()){
169 this->wait(mutex);
170 }
171}
172
173template<typename Pred>
174bool original::conditionBase::waitFor(mutexBase& mutex, const time::duration& d, Pred predicate) noexcept(noexcept(predicate())) {
175 const time::point start = time::point::now();
176 while (!predicate()) {
177 auto elapsed = time::point::now() - start;
178 if (elapsed >= d)
179 return false;
180 if (!this->waitFor(mutex, d - elapsed))
181 return false;
182 if (predicate())
183 return true;
184 }
185 return true;
186}
187
189{
190 if (const int code = pthread_cond_init(&this->cond_, nullptr); code != 0)
191 {
192 throw sysError("Failed to initialize condition variable (pthread_cond_init returned " + printable::formatString(code) + ")");
193 }
194}
195
197{
198 const auto p_mutex = dynamic_cast<pMutex*>(&mutex);
199 if (!p_mutex) {
200 throw valueError("Invalid mutex type for condition variable: must be pMutex");
201 }
202
203 const auto handle = static_cast<pMutex::native_handle*>(p_mutex->nativeHandle());
204 if (const int code = pthread_cond_wait(&this->cond_, handle); code != 0) {
205 throw sysError("Failed to wait on condition variable (pthread_cond_wait returned " + printable::formatString(code) + ")");
206 }
207}
208
210{
211 const auto p_mutex = dynamic_cast<pMutex*>(&mutex);
212 if (!p_mutex) {
213 throw valueError("Invalid mutex type for condition variable: must be pMutex");
214 }
215
216 const auto deadline = time::point::now() + d;
217 const auto ts = deadline.toTimespec();
218 const auto handle = static_cast<pMutex::native_handle*>(p_mutex->nativeHandle());
219 const int code = pthread_cond_timedwait(&this->cond_, handle, &ts);
220 if (code == 0) return true;
221 if (code == ETIMEDOUT) return false;
222 throw sysError("Failed to timed wait on condition variable (pthread_cond_timed-wait returned " + printable::formatString(code) + ")");
223}
224
226{
227 if (const int code = pthread_cond_signal(&this->cond_); code != 0) {
228 throw sysError("Failed to signal condition variable (pthread_cond_signal returned " + printable::formatString(code) + ")");
229 }
230}
231
233{
234 if (const int code = pthread_cond_broadcast(&this->cond_); code != 0) {
235 throw sysError("Failed to broadcast condition variable (pthread_cond_broadcast returned " + printable::formatString(code) + ")");
236 }
237}
238
240{
241 if (const int code = pthread_cond_destroy(&this->cond_); code != 0) {
242 std::cerr << "Warning: Failed to destroy condition variable (pthread_cond_destroy returned "
243 << code << ")" << std::endl;
244 }
245}
246
247#endif //CONDITION_H
Abstract base class for condition variable implementations.
Definition condition.h:38
virtual void notifyAll()=0
Notifies all waiting threads.
conditionBase & operator=(const conditionBase &)=delete
Deleted copy assignment operator.
virtual void wait(mutexBase &mutex)=0
Waits for notification while holding the mutex.
conditionBase(const conditionBase &)=delete
Deleted copy constructor.
virtual bool waitFor(mutexBase &mutex, time::duration d)=0
Waits for notification with timeout.
virtual ~conditionBase()=default
Virtual destructor.
conditionBase()=default
Default constructor.
virtual void notify()=0
Notifies one waiting thread.
Abstract base class for mutex implementations.
Definition mutex.h:30
POSIX condition variable implementation.
Definition condition.h:114
void wait(mutexBase &mutex) override
Waits for notification while holding the mutex.
Definition condition.h:196
bool waitFor(mutexBase &mutex, time::duration d) override
Waits for notification with timeout.
Definition condition.h:209
void notifyAll() override
Notifies all waiting threads.
Definition condition.h:232
void notify() override
Notifies one waiting thread.
Definition condition.h:225
~pCondition() override
Destroys the condition variable.
Definition condition.h:239
pCondition()
Constructs and initializes the condition variable.
Definition condition.h:188
POSIX thread mutex implementation.
Definition mutex.h:153
pthread_mutex_t native_handle
Native handle type (pthread_mutex_t)
Definition mutex.h:157
static std::string formatString(const TYPE &t)
Universal value-to-string conversion.
Definition printable.h:263
Exception for generic system failure.
Definition error.h:306
Represents a time duration with nanosecond precision.
Definition zeit.h:134
Represents a point in time with nanosecond precision.
Definition zeit.h:374
static point now()
Gets current time point.
Definition zeit.h:1352
Exception for invalid parameter values.
Definition error.h:150
Cross-platform mutex and lock management utilities.
Main namespace for the project Original.
Definition algorithms.h:21
Time and date handling utilities.