1 | // |
2 | // Semaphore.h |
3 | // |
4 | // Library: Foundation |
5 | // Package: Threading |
6 | // Module: Semaphore |
7 | // |
8 | // Definition of the Semaphore class. |
9 | // |
10 | // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. |
11 | // and Contributors. |
12 | // |
13 | // SPDX-License-Identifier: BSL-1.0 |
14 | // |
15 | |
16 | |
17 | #ifndef Foundation_Semaphore_INCLUDED |
18 | #define Foundation_Semaphore_INCLUDED |
19 | |
20 | |
21 | #include "Poco/Foundation.h" |
22 | #include "Poco/Exception.h" |
23 | #include <mutex> |
24 | #include <condition_variable> |
25 | |
26 | |
27 | namespace Poco { |
28 | |
29 | |
30 | class Foundation_API Semaphore |
31 | /// A Semaphore is a synchronization object with the following |
32 | /// characteristics: |
33 | /// A semaphore has a value that is constrained to be a non-negative |
34 | /// integer and two atomic operations. The allowable operations are V |
35 | /// (here called set()) and P (here called wait()). A V (set()) operation |
36 | /// increases the value of the semaphore by one. |
37 | /// A P (wait()) operation decreases the value of the semaphore by one, |
38 | /// provided that can be done without violating the constraint that the |
39 | /// value be non-negative. A P (wait()) operation that is initiated when |
40 | /// the value of the semaphore is 0 suspends the calling thread. |
41 | /// The calling thread may continue when the value becomes positive again. |
42 | { |
43 | public: |
44 | Semaphore(int n); |
45 | Semaphore(int n, int max); |
46 | /// Creates the semaphore. The current value |
47 | /// of the semaphore is given in n. The |
48 | /// maximum value of the semaphore is given |
49 | /// in max. |
50 | /// If only n is given, it must be greater than |
51 | /// zero. |
52 | /// If both n and max are given, max must be |
53 | /// greater than zero, n must be greater than |
54 | /// or equal to zero and less than or equal |
55 | /// to max. |
56 | |
57 | ~Semaphore(); |
58 | /// Destroys the semaphore. |
59 | |
60 | void set(); |
61 | /// Increments the semaphore's value by one and |
62 | /// thus signals the semaphore. Another thread |
63 | /// waiting for the semaphore will be able |
64 | /// to continue. |
65 | |
66 | void wait(); |
67 | /// Waits for the semaphore to become signalled. |
68 | /// To become signalled, a semaphore's value must |
69 | /// be greater than zero. |
70 | /// Decrements the semaphore's value by one. |
71 | |
72 | void wait(long milliseconds); |
73 | /// Waits for the semaphore to become signalled. |
74 | /// To become signalled, a semaphore's value must |
75 | /// be greater than zero. |
76 | /// Throws a TimeoutException if the semaphore |
77 | /// does not become signalled within the specified |
78 | /// time interval. |
79 | /// Decrements the semaphore's value by one |
80 | /// if successful. |
81 | |
82 | bool tryWait(long milliseconds); |
83 | /// Waits for the semaphore to become signalled. |
84 | /// To become signalled, a semaphore's value must |
85 | /// be greater than zero. |
86 | /// Returns true if the semaphore |
87 | /// became signalled within the specified |
88 | /// time interval, false otherwise. |
89 | /// Decrements the semaphore's value by one |
90 | /// if successful. |
91 | |
92 | private: |
93 | Semaphore(); |
94 | Semaphore(const Semaphore&); |
95 | Semaphore& operator = (const Semaphore&); |
96 | |
97 | bool waitImpl(long milliseconds); |
98 | |
99 | int _count; |
100 | int _max; |
101 | std::mutex _mutex; |
102 | std::condition_variable _cv; |
103 | }; |
104 | |
105 | |
106 | // |
107 | // inlines |
108 | // |
109 | |
110 | inline void Semaphore::wait(long milliseconds) |
111 | { |
112 | if (!waitImpl(milliseconds)) throw TimeoutException(); |
113 | } |
114 | |
115 | |
116 | inline bool Semaphore::tryWait(long milliseconds) |
117 | { |
118 | return waitImpl(milliseconds); |
119 | } |
120 | |
121 | |
122 | } // namespace Poco |
123 | |
124 | |
125 | #endif // Foundation_Semaphore_INCLUDED |
126 | |