1//
2// Condition.h
3//
4// Library: Foundation
5// Package: Threading
6// Module: Condition
7//
8// Definition of the Condition class template.
9//
10// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
11// and Contributors.
12//
13// SPDX-License-Identifier: BSL-1.0
14//
15
16
17#ifndef Foundation_Condition_INCLUDED
18#define Foundation_Condition_INCLUDED
19
20
21#include "Poco/Foundation.h"
22#include "Poco/Mutex.h"
23#include "Poco/ScopedUnlock.h"
24#include "Poco/Event.h"
25#include "Poco/Exception.h"
26#include <deque>
27
28
29namespace Poco {
30
31
32class Foundation_API Condition
33 /// A Condition is a synchronization object used to block a thread
34 /// until a particular condition is met.
35 /// A Condition object is always used in conjunction with
36 /// a Mutex (or FastMutex) object.
37 ///
38 /// Condition objects are similar to POSIX condition variables, which the
39 /// difference that Condition is not subject to spurious wakeups.
40 ///
41 /// Threads waiting on a Condition are resumed in FIFO order.
42{
43public:
44 Condition();
45 /// Creates the Condition.
46
47 ~Condition();
48 /// Destroys the Condition.
49
50 template <class Mtx>
51 void wait(Mtx& mutex)
52 /// Unlocks the mutex (which must be locked upon calling
53 /// wait()) and waits until the Condition is signalled.
54 ///
55 /// The given mutex will be locked again upon
56 /// leaving the function, even in case of an exception.
57 {
58 ScopedUnlock<Mtx> unlock(mutex, false);
59 Event event;
60 {
61 FastMutex::ScopedLock lock(_mutex);
62 mutex.unlock();
63 enqueue(event);
64 }
65 event.wait();
66 }
67
68 template <class Mtx>
69 void wait(Mtx& mutex, long milliseconds)
70 /// Unlocks the mutex (which must be locked upon calling
71 /// wait()) and waits for the given time until the Condition is signalled.
72 ///
73 /// The given mutex will be locked again upon successfully leaving the
74 /// function, even in case of an exception.
75 ///
76 /// Throws a TimeoutException if the Condition is not signalled
77 /// within the given time interval.
78 {
79 if (!tryWait(mutex, milliseconds))
80 throw TimeoutException();
81 }
82
83 template <class Mtx>
84 bool tryWait(Mtx& mutex, long milliseconds)
85 /// Unlocks the mutex (which must be locked upon calling
86 /// tryWait()) and waits for the given time until the Condition is signalled.
87 ///
88 /// The given mutex will be locked again upon leaving the
89 /// function, even in case of an exception.
90 ///
91 /// Returns true if the Condition has been signalled
92 /// within the given time interval, otherwise false.
93 {
94 ScopedUnlock<Mtx> unlock(mutex, false);
95 Event event;
96 {
97 FastMutex::ScopedLock lock(_mutex);
98 mutex.unlock();
99 enqueue(event);
100 }
101 if (!event.tryWait(milliseconds))
102 {
103 FastMutex::ScopedLock lock(_mutex);
104 dequeue(event);
105 return false;
106 }
107 return true;
108 }
109
110 void signal();
111 /// Signals the Condition and allows one waiting thread
112 /// to continue execution.
113
114 void broadcast();
115 /// Signals the Condition and allows all waiting
116 /// threads to continue their execution.
117
118protected:
119 void enqueue(Event& event);
120 void dequeue();
121 void dequeue(Event& event);
122
123private:
124 Condition(const Condition&);
125 Condition& operator = (const Condition&);
126
127 typedef std::deque<Event*> WaitQueue;
128
129 FastMutex _mutex;
130 WaitQueue _waitQueue;
131};
132
133
134} // namespace Poco
135
136
137#endif // Foundation_Condition_INCLUDED
138