BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslmt_timedsemaphore.h
Go to the documentation of this file.
1/// @file bslmt_timedsemaphore.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslmt_timedsemaphore.h -*-C++-*-
8#ifndef INCLUDED_BSLMT_TIMEDSEMAPHORE
9#define INCLUDED_BSLMT_TIMEDSEMAPHORE
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslmt_timedsemaphore bslmt_timedsemaphore
15/// @brief Provide a timed semaphore class.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslmt
19/// @{
20/// @addtogroup bslmt_timedsemaphore
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslmt_timedsemaphore-purpose"> Purpose</a>
25/// * <a href="#bslmt_timedsemaphore-classes"> Classes </a>
26/// * <a href="#bslmt_timedsemaphore-description"> Description </a>
27/// * <a href="#bslmt_timedsemaphore-supported-clock-types"> Supported Clock-Types </a>
28/// * <a href="#bslmt_timedsemaphore-usage"> Usage </a>
29/// * <a href="#bslmt_timedsemaphore-example-1-basic-usage"> Example 1: Basic Usage </a>
30///
31/// # Purpose {#bslmt_timedsemaphore-purpose}
32/// Provide a timed semaphore class.
33///
34/// # Classes {#bslmt_timedsemaphore-classes}
35///
36/// - bslmt::TimedSemaphore: timed semaphore class
37///
38/// @see bslmt_semaphore
39///
40/// # Description {#bslmt_timedsemaphore-description}
41/// This component defines a portable and efficient thread
42/// synchronization primitive. In particular, `bslmt::TimedSemaphore` is an
43/// efficient synchronization primitive that enables sharing of a counted number
44/// of resources or exclusive access.
45///
46/// `bslmt::TimedSemaphore` differs from `bslmt::Semaphore` in that the former
47/// supports a `timedWait` method, whereas the latter does not. In addition,
48/// `bslmt::Semaphore` has a `getValue` accessor, whereas
49/// `bslmt::TimedSemaphore` does not. In the case of the timed semaphore,
50/// `getValue` cannot be implemented efficiently on all platforms, so that
51/// method is *intentionally* not provided.
52///
53/// ## Supported Clock-Types {#bslmt_timedsemaphore-supported-clock-types}
54///
55///
56/// `bsls::SystemClockType` supplies the enumeration indicating the system clock
57/// on which timeouts supplied to other methods should be based. If the clock
58/// type indicated at construction is `bsls::SystemClockType::e_REALTIME`, the
59/// `absTime` argument passed to the `timedWait` method should be expressed as
60/// an *absolute* offset since 00:00:00 UTC, January 1, 1970 (which matches the
61/// epoch used in `bsls::SystemTime::now(bsls::SystemClockType::e_REALTIME)`.
62/// If the clock type indicated at construction is
63/// `bsls::SystemClockType::e_MONOTONIC`, the `absTime` argument passed to the
64/// `timedWait` method should be expressed as an *absolute* offset since the
65/// epoch of this clock (which matches the epoch used in
66/// `bsls::SystemTime::now(bsls::SystemClockType::e_MONOTONIC)`.
67///
68/// On platforms that support `bsl::chrono`, there are constructors that take
69/// `bsl::chrono`-style clocks. If the clock type indicated at construction is
70/// `bsl::chrono::system_clock`, then the results will be the same as if
71/// `bsls::SystemClockType::e_REALTIME` was indicated. If the clock type
72/// indicated at construction is `bsl::chrono::steady_clock`, then the results
73/// will be the same as if `bsls::SystemClockType::e_MONOTONIC` was indicated.
74/// Constructing from a user-defined clock is not supported.
75///
76/// ## Usage {#bslmt_timedsemaphore-usage}
77///
78///
79/// This section illustrates intended use of this component.
80///
81/// ### Example 1: Basic Usage {#bslmt_timedsemaphore-example-1-basic-usage}
82///
83///
84/// This example illustrates a very simple queue where potential clients can
85/// push integers to a queue, and later retrieve the integer values from the
86/// queue in FIFO order. It illustrates two potential uses of semaphores: to
87/// enforce exclusive access, and to allow resource sharing. This queue allows
88/// clients to set a limit on how long they wait to retrieve values.
89/// @code
90/// /// FIFO queue of integer values.
91/// class IntQueue {
92///
93/// // DATA
94/// bsl::deque<int> d_queue; // underlying queue
95/// bslmt::TimedSemaphore d_resourceSem; // resource-availability semaphore
96/// bslmt::TimedSemaphore d_mutexSem; // mutual-access semaphore
97///
98/// // NOT IMPLEMENTED
99/// IntQueue(const IntQueue&);
100/// IntQueue& operator=(const IntQueue&);
101///
102/// public:
103/// // CREATORS
104///
105/// /// Create an `IntQueue` object. Optionally specified a
106/// /// `basicAllocator` used to supply memory. If `basicAllocator` is
107/// /// 0, the currently installed default allocator is used.
108/// explicit IntQueue(bslma::Allocator *basicAllocator = 0);
109///
110/// /// Destroy this `IntQueue` object.
111/// ~IntQueue();
112///
113/// // MANIPULATORS
114///
115/// /// Load the first integer in this queue into the specified `result`
116/// /// and return 0 unless the operation takes more than the optionally
117/// /// specified `maxWaitSeconds`, in which case return a nonzero value
118/// /// and leave `result` unmodified.
119/// int getInt(int *result, int maxWaitSeconds = 0);
120///
121/// /// Push the specified `value` to this `IntQueue` object.
122/// void pushInt(int value);
123/// };
124/// @endcode
125/// Note that the `IntQueue` constructor increments the count of the semaphore
126/// to 1 so that values can be pushed into the queue immediately following
127/// construction:
128/// @code
129/// // CREATORS
130/// IntQueue::IntQueue(bslma::Allocator *basicAllocator)
131/// : d_queue(basicAllocator)
132/// , d_resourceSem(bsls::SystemClockType::e_MONOTONIC)
133/// {
134/// d_mutexSem.post();
135/// }
136///
137/// IntQueue::~IntQueue()
138/// {
139/// d_mutexSem.wait(); // Wait for potential modifier.
140/// }
141///
142/// // MANIPULATORS
143/// int IntQueue::getInt(int *result, int maxWaitSeconds)
144/// {
145/// // Waiting for resources.
146/// if (0 == maxWaitSeconds) {
147/// d_resourceSem.wait();
148/// } else {
149/// bsls::TimeInterval absTime = bsls::SystemTime::nowMonotonicClock()
150/// .addSeconds(maxWaitSeconds);
151/// int rc = d_resourceSem.timedWait(absTime);
152/// if (0 != rc) {
153/// return rc;
154/// }
155/// }
156///
157/// // 'd_mutexSem' is used for exclusive access.
158/// d_mutexSem.wait(); // lock
159/// *result = d_queue.back();
160/// d_queue.pop_back();
161/// d_mutexSem.post(); // unlock
162///
163/// return 0;
164/// }
165///
166/// void IntQueue::pushInt(int value)
167/// {
168/// d_mutexSem.wait();
169/// d_queue.pushFront(value);
170/// d_mutexSem.post();
171///
172/// d_resourceSem.post(); // Signal that we have resources available.
173/// }
174/// @endcode
175/// @}
176/** @} */
177/** @} */
178
179/** @addtogroup bsl
180 * @{
181 */
182/** @addtogroup bslmt
183 * @{
184 */
185/** @addtogroup bslmt_timedsemaphore
186 * @{
187 */
188
189#include <bslscm_version.h>
190
191#include <bslmt_chronoutil.h>
192#include <bslmt_platform.h>
196
197#include <bsls_libraryfeatures.h>
198#include <bsls_systemclocktype.h>
199#include <bsls_systemtime.h>
200#include <bsls_timeinterval.h>
201
202#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
203#include <bsl_chrono.h>
204#endif
205
206
207namespace bslmt {
208
209template <class TIMED_SEMAPHORE_POLICY>
211
212 // ====================
213 // class TimedSemaphore
214 // ====================
215
216/// This class implements a portable timed semaphore type for thread
217/// synchronization. It forwards all requests to an appropriate
218/// platform-specific implementation.
219///
220/// See @ref bslmt_timedsemaphore
222
223 // DATA
225 // platform-specific implementation
226 // NOT IMPLEMENTED
228 TimedSemaphore& operator=(const TimedSemaphore&);
229
230 public:
231 // TYPES
232
233 /// The value `timedWait` returns when a timeout occurs.
234 enum { e_TIMED_OUT =
236
237 // CREATORS
238
239 /// Create a timed semaphore initially having a count of 0. Optionally
240 /// specify a `clockType` indicating the type of the system clock
241 /// against which the `absTime` timeouts passed to the `timedWait`
242 /// methods are to be interpreted (see {Supported Clock-Types} in the
243 /// component-level documentation). If `clockType` is not specified
244 /// then the realtime system clock is used. This method does
245 /// not return normally unless there are sufficient system resources to
246 /// construct the object.
247 explicit
250
251#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
252 /// Create a timed semaphore initially having a count of 0. Use the
253 /// realtime system clock as the clock against which the `absTime`
254 /// timeouts passed to the `timedWait` methods are interpreted (see
255 /// {Supported Clock-Types} in the component-level documentation).
256 /// This method does not return normally unless there are sufficient
257 /// system resources to construct the object.
258 explicit
259 TimedSemaphore(const bsl::chrono::system_clock&);
260
261 /// Create a timed semaphore initially having a count of 0. Use the
262 /// monotonic system clock as the clock against which the `absTime`
263 /// timeouts passed to the `timedWait` methods are interpreted (see
264 /// {Supported Clock-Types} in the component-level documentation).
265 /// This method does not return normally unless there are sufficient
266 /// system resources to construct the object.
267 explicit
268 TimedSemaphore(const bsl::chrono::steady_clock&);
269#endif
270
271 /// Create a timed semaphore initially having the specified `count`.
272 /// Optionally specify a `clockType` indicating the type of the system
273 /// clock against which the `absTime` timeouts passed to the `timedWait`
274 /// methods are to be interpreted (see {Supported Clock-Types} in the
275 /// component-level documentation). If `clockType` is not specified
276 /// then the realtime system clock is used. This method does not return
277 /// normally unless there are sufficient system resources to construct
278 /// the object. The behavior is undefined unless `0 <= count`.
279 explicit
281 int count,
283
284#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
285 /// Create a timed semaphore initially having the specified `count`.
286 /// Use the realtime system clock as the clock against which the
287 /// `absTime` timeouts passed to the `timedWait` methods are interpreted
288 /// (see {Supported Clock-Types} in the component-level documentation).
289 /// This method does not return normally unless there are sufficient
290 /// system resources to construct the object. The behavior is undefined
291 /// unless `0 <= count`.
292 TimedSemaphore(int count, const bsl::chrono::system_clock&);
293
294 /// Create a timed semaphore initially having the specified `count`.
295 /// Use the monotonic system clock as the clock against which the
296 /// `absTime` timeouts passed to the `timedWait` methods are interpreted
297 /// (see {Supported Clock-Types} in the component-level documentation).
298 /// This method does not return normally unless there are sufficient
299 /// system resources to construct the object. The behavior is undefined
300 /// unless `0 <= count`.
301 TimedSemaphore(int count, const bsl::chrono::steady_clock&);
302#endif
303
304 /// Destroy this timed semaphore.
306
307 // MANIPULATORS
308
309 /// Atomically increment the count of this timed semaphore.
310 void post();
311
312 /// Atomically increase the count of this timed semaphore by the
313 /// specified `value`. The behavior is undefined unless `value > 0`.
314 void post(int value);
315
316 /// Block until the count of this semaphore is a positive value, or
317 /// until the specified `absTime` timeout expires. `absTime` is an
318 /// *absolute* time represented as an interval from some epoch, which is
319 /// determined by the clock indicated at construction (see {Supported
320 /// Clock-Types} in the component-level documentation). If the
321 /// `absTime` timeout did not expire before the count attained a
322 /// positive value, atomically decrement the count and return 0. If the
323 /// `absTime` timeout did expire, return `e_TIMED_OUT` with no effect
324 /// on the count. Any other value indicates that an error has occurred.
325 /// Errors are unrecoverable. After an error, the semaphore may be
326 /// destroyed, but any other use has undefined behavior. On Windows
327 /// platforms, this method may return `e_TIMED_OUT` slightly before
328 /// `absTime`.
329 int timedWait(const bsls::TimeInterval& absTime);
330
331#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
332 /// Block until the count of this semaphore is a positive value, or
333 /// until the specified `absTime` timeout expires. `absTime` is an
334 /// *absolute* time represented by a time point with respect to some
335 /// epoch, which is determined by the clock associated with the time
336 /// point. If the `absTime` timeout did not expire before the count
337 /// attained a positive value, atomically decrement the count and return
338 /// 0. If the `absTime` timeout did expire, return `e_TIMED_OUT` with
339 /// no effect on the count. Any other value indicates that an error has
340 /// occurred. Errors are unrecoverable. After an error, the semaphore
341 /// may be destroyed, but any other use has undefined behavior. On
342 /// Windows platforms, this method may return `e_TIMED_OUT` slightly
343 /// before `absTime`.
344 template <class CLOCK, class DURATION>
345 int timedWait(const bsl::chrono::time_point<CLOCK, DURATION>& absTime);
346#endif
347
348 /// If the count of this timed semaphore is positive, atomically
349 /// decrement the count and return 0; otherwise, return a non-zero value
350 /// with no effect on the count.
351 int tryWait();
352
353 /// Block until the count of this timed semaphore is a positive value,
354 /// then atomically decrement the count and return.
355 void wait();
356
357 // ACCESSORS
358
359 /// Return the clock type used for timeouts.
361};
362
363// ============================================================================
364// INLINE DEFINITIONS
365// ============================================================================
366
367 // --------------------
368 // class TimedSemaphore
369 // --------------------
370
371// CREATORS
372inline
373TimedSemaphore::TimedSemaphore(bsls::SystemClockType::Enum clockType)
374: d_impl(clockType)
375{
376}
377
378#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
379inline
380TimedSemaphore::TimedSemaphore(const bsl::chrono::system_clock&)
381: d_impl(bsls::SystemClockType::e_REALTIME)
382{
383}
384
385inline
386TimedSemaphore::TimedSemaphore(const bsl::chrono::steady_clock&)
387: d_impl(bsls::SystemClockType::e_MONOTONIC)
388{
389}
390#endif
391
392inline
393TimedSemaphore::TimedSemaphore(int count,
395: d_impl(count, clockType)
396{
397}
398
399#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
400inline
401TimedSemaphore::TimedSemaphore(int count,
402 const bsl::chrono::system_clock&)
403: d_impl(count, bsls::SystemClockType::e_REALTIME)
404{
405}
406
407inline
408TimedSemaphore::TimedSemaphore(int count,
409 const bsl::chrono::steady_clock&)
410: d_impl(count, bsls::SystemClockType::e_MONOTONIC)
411{
412}
413#endif
414
415inline
419
420// MANIPULATORS
421inline
423{
424 d_impl.post();
425}
426
427inline
428void TimedSemaphore::post(int value)
429{
430 d_impl.post(value);
431}
432
433inline
435{
436 return d_impl.timedWait(absTime);
437}
438
439#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
440template <class CLOCK, class DURATION>
441inline
443 const bsl::chrono::time_point<CLOCK, DURATION>& absTime)
444{
445 return bslmt::ChronoUtil::timedWait(this, absTime);
446}
447#endif
448
449inline
451{
452 return d_impl.tryWait();
453}
454
455inline
457{
458 d_impl.wait();
459}
460
461// ACCESSORS
462inline
465{
466 return d_impl.clockType();
467}
468
469} // close package namespace
470
471
472#endif
473
474// ----------------------------------------------------------------------------
475// Copyright 2023 Bloomberg Finance L.P.
476//
477// Licensed under the Apache License, Version 2.0 (the "License");
478// you may not use this file except in compliance with the License.
479// You may obtain a copy of the License at
480//
481// http://www.apache.org/licenses/LICENSE-2.0
482//
483// Unless required by applicable law or agreed to in writing, software
484// distributed under the License is distributed on an "AS IS" BASIS,
485// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
486// See the License for the specific language governing permissions and
487// limitations under the License.
488// ----------------------------- END-OF-FILE ----------------------------------
489
490/** @} */
491/** @} */
492/** @} */
Definition bslmt_timedsemaphore.h:210
Definition bslmt_timedsemaphore.h:221
void post()
Atomically increment the count of this timed semaphore.
Definition bslmt_timedsemaphore.h:422
~TimedSemaphore()
Destroy this timed semaphore.
Definition bslmt_timedsemaphore.h:416
bsls::SystemClockType::Enum clockType() const
Return the clock type used for timeouts.
Definition bslmt_timedsemaphore.h:464
void wait()
Definition bslmt_timedsemaphore.h:456
@ e_TIMED_OUT
Definition bslmt_timedsemaphore.h:234
int tryWait()
Definition bslmt_timedsemaphore.h:450
int timedWait(const bsls::TimeInterval &absTime)
Definition bslmt_timedsemaphore.h:434
Definition bsls_timeinterval.h:301
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bslmt_barrier.h:344
Definition bdlt_iso8601util.h:691
static int timedWait(PRIMITIVE *primitive, const bsl::chrono::time_point< CLOCK, DURATION > &absTime)
Definition bslmt_chronoutil.h:345
Enum
Definition bsls_systemclocktype.h:117
@ e_REALTIME
Definition bsls_systemclocktype.h:120