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 29 namespace Poco { 30 31 32 class 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 { 43 public: 44 Condition(); 45 /// Creates the Condition. 46 47 ~Condition(); 48 /// Destroys the Condition. 49 50 template <class Mtx> wait(Mtx & mutex)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> wait(Mtx & mutex,long milliseconds)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> tryWait(Mtx & mutex,long milliseconds)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 118 protected: 119 void enqueue(Event& event); 120 void dequeue(); 121 void dequeue(Event& event); 122 123 private: 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