BDE 4.39.x 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/// private:
99/// // NOT IMPLEMENTED
100/// IntQueue(const IntQueue&);
101/// IntQueue& operator=(const IntQueue&);
102///
103/// public:
104/// // CREATORS
105///
106/// /// Create an `IntQueue` object. Optionally specified a
107/// /// `basicAllocator` used to supply memory. If `basicAllocator` is
108/// /// 0, the currently installed default allocator is used.
109/// explicit IntQueue(bslma::Allocator *basicAllocator = 0);
110///
111/// /// Destroy this `IntQueue` object.
112/// ~IntQueue();
113///
114/// // MANIPULATORS
115///
116/// /// Load the first integer in this queue into the specified `result`
117/// /// and return 0 unless the operation takes more than the optionally
118/// /// specified `maxWaitSeconds`, in which case return a nonzero value
119/// /// and leave `result` unmodified.
120/// int getInt(int *result, int maxWaitSeconds = 0);
121///
122/// /// Push the specified `value` to this `IntQueue` object.
123/// void pushInt(int value);
124/// };
125/// @endcode
126/// Note that the `IntQueue` constructor increments the count of the semaphore
127/// to 1 so that values can be pushed into the queue immediately following
128/// construction:
129/// @code
130/// // CREATORS
131/// IntQueue::IntQueue(bslma::Allocator *basicAllocator)
132/// : d_queue(basicAllocator)
133/// , d_resourceSem(bsls::SystemClockType::e_MONOTONIC)
134/// {
135/// d_mutexSem.post();
136/// }
137///
138/// IntQueue::~IntQueue()
139/// {
140/// d_mutexSem.wait(); // Wait for potential modifier.
141/// }
142///
143/// // MANIPULATORS
144/// int IntQueue::getInt(int *result, int maxWaitSeconds)
145/// {
146/// // Waiting for resources.
147/// if (0 == maxWaitSeconds) {
148/// d_resourceSem.wait();
149/// } else {
150/// bsls::TimeInterval absTime = bsls::SystemTime::nowMonotonicClock()
151/// .addSeconds(maxWaitSeconds);
152/// int rc = d_resourceSem.timedWait(absTime);
153/// if (0 != rc) {
154/// return rc;
155/// }
156/// }
157///
158/// // 'd_mutexSem' is used for exclusive access.
159/// d_mutexSem.wait(); // lock
160/// *result = d_queue.back();
161/// d_queue.pop_back();
162/// d_mutexSem.post(); // unlock
163///
164/// return 0;
165/// }
166///
167/// void IntQueue::pushInt(int value)
168/// {
169/// d_mutexSem.wait();
170/// d_queue.pushFront(value);
171/// d_mutexSem.post();
172///
173/// d_resourceSem.post(); // Signal that we have resources available.
174/// }
175/// @endcode
176/// @}
177/** @} */
178/** @} */
179
180/** @addtogroup bsl
181 * @{
182 */
183/** @addtogroup bslmt
184 * @{
185 */
186/** @addtogroup bslmt_timedsemaphore
187 * @{
188 */
189
190#include <bslscm_version.h>
191
192#include <bslmt_chronoutil.h>
193#include <bslmt_platform.h>
197
198#include <bsls_libraryfeatures.h>
199#include <bsls_systemclocktype.h>
200#include <bsls_systemtime.h>
201#include <bsls_timeinterval.h>
202
203#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
204#include <bsl_chrono.h>
205#endif
206
207
208namespace bslmt {
209
210template <class TIMED_SEMAPHORE_POLICY>
212
213 // ====================
214 // class TimedSemaphore
215 // ====================
216
217/// This class implements a portable timed semaphore type for thread
218/// synchronization. It forwards all requests to an appropriate
219/// platform-specific implementation.
220///
221/// See @ref bslmt_timedsemaphore
223
224 // DATA
226 // platform-specific implementation
227 private:
228 // NOT IMPLEMENTED
230 TimedSemaphore& operator=(const TimedSemaphore&);
231
232 public:
233 // TYPES
234
235 /// The value `timedWait` returns when a timeout occurs.
236 enum { e_TIMED_OUT =
238
239 // CREATORS
240
241 /// Create a timed semaphore initially having a count of 0. Optionally
242 /// specify a `clockType` indicating the type of the system clock
243 /// against which the `absTime` timeouts passed to the `timedWait`
244 /// methods are to be interpreted (see {Supported Clock-Types} in the
245 /// component-level documentation). If `clockType` is not specified
246 /// then the realtime system clock is used. This method does
247 /// not return normally unless there are sufficient system resources to
248 /// construct the object.
249 explicit
252
253#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
254 /// Create a timed semaphore initially having a count of 0. Use the
255 /// realtime system clock as the clock against which the `absTime`
256 /// timeouts passed to the `timedWait` methods are interpreted (see
257 /// {Supported Clock-Types} in the component-level documentation).
258 /// This method does not return normally unless there are sufficient
259 /// system resources to construct the object.
260 explicit
261 TimedSemaphore(const bsl::chrono::system_clock&);
262
263 /// Create a timed semaphore initially having a count of 0. Use the
264 /// monotonic system clock as the clock against which the `absTime`
265 /// timeouts passed to the `timedWait` methods are interpreted (see
266 /// {Supported Clock-Types} in the component-level documentation).
267 /// This method does not return normally unless there are sufficient
268 /// system resources to construct the object.
269 explicit
270 TimedSemaphore(const bsl::chrono::steady_clock&);
271#endif
272
273 /// Create a timed semaphore initially having the specified `count`.
274 /// Optionally specify a `clockType` indicating the type of the system
275 /// clock against which the `absTime` timeouts passed to the `timedWait`
276 /// methods are to be interpreted (see {Supported Clock-Types} in the
277 /// component-level documentation). If `clockType` is not specified
278 /// then the realtime system clock is used. This method does not return
279 /// normally unless there are sufficient system resources to construct the object.
280 ///
281 /// \pre The behavior is undefined unless `0 <= count`.
282 explicit
284 int count,
286
287#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
288 /// Create a timed semaphore initially having the specified `count`.
289 /// Use the realtime system clock as the clock against which the
290 /// `absTime` timeouts passed to the `timedWait` methods are interpreted
291 /// (see {Supported Clock-Types} in the component-level documentation).
292 /// This method does not return normally unless there are sufficient
293 /// system resources to construct the object.
294 ///
295 /// \pre The behavior is undefined unless `0 <= count`.
296 TimedSemaphore(int count, const bsl::chrono::system_clock&);
297
298 /// Create a timed semaphore initially having the specified `count`.
299 /// Use the monotonic system clock as the clock against which the
300 /// `absTime` timeouts passed to the `timedWait` methods are interpreted
301 /// (see {Supported Clock-Types} in the component-level documentation).
302 /// This method does not return normally unless there are sufficient
303 /// system resources to construct the object.
304 ///
305 /// \pre The behavior is undefined unless `0 <= count`.
306 TimedSemaphore(int count, const bsl::chrono::steady_clock&);
307#endif
308
309 /// Destroy this timed semaphore.
311
312 // MANIPULATORS
313
314 /// Atomically increment the count of this timed semaphore.
315 void post();
316
317 /// Atomically increase the count of this timed semaphore by the specified `value`.
318 ///
319 /// \pre The behavior is undefined unless `value > 0`.
320 void post(int value);
321
322 /// Block until the count of this semaphore is a positive value, or
323 /// until the specified `absTime` timeout expires. `absTime` is an
324 /// *absolute* time represented as an interval from some epoch, which is
325 /// determined by the clock indicated at construction (see {Supported
326 /// Clock-Types} in the component-level documentation). If the
327 /// `absTime` timeout did not expire before the count attained a
328 /// positive value, atomically decrement the count and return 0. If the
329 /// `absTime` timeout did expire, return `e_TIMED_OUT` with no effect
330 /// on the count. Any other value indicates that an error has occurred.
331 /// Errors are unrecoverable. After an error, the semaphore may be
332 /// destroyed, but any other use has undefined behavior. On Windows
333 /// platforms, this method may return `e_TIMED_OUT` slightly before
334 /// `absTime`.
335 int timedWait(const bsls::TimeInterval& absTime);
336
337#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
338 /// Block until the count of this semaphore is a positive value, or
339 /// until the specified `absTime` timeout expires. `absTime` is an
340 /// *absolute* time represented by a time point with respect to some
341 /// epoch, which is determined by the clock associated with the time
342 /// point. If the `absTime` timeout did not expire before the count
343 /// attained a positive value, atomically decrement the count and return
344 /// 0. If the `absTime` timeout did expire, return `e_TIMED_OUT` with
345 /// no effect on the count. Any other value indicates that an error has
346 /// occurred. Errors are unrecoverable. After an error, the semaphore
347 /// may be destroyed, but any other use has undefined behavior. On
348 /// Windows platforms, this method may return `e_TIMED_OUT` slightly
349 /// before `absTime`.
350 template <class CLOCK, class DURATION>
351 int timedWait(const bsl::chrono::time_point<CLOCK, DURATION>& absTime);
352#endif
353
354 /// If the count of this timed semaphore is positive, atomically
355 /// decrement the count and return 0; otherwise, return a non-zero value
356 /// with no effect on the count.
357 int tryWait();
358
359 /// Block until the count of this timed semaphore is a positive value,
360 /// then atomically decrement the count and return.
361 void wait();
362
363 // ACCESSORS
364
365 /// Return the clock type used for timeouts.
367};
368
369// ============================================================================
370// INLINE DEFINITIONS
371// ============================================================================
372
373 // --------------------
374 // class TimedSemaphore
375 // --------------------
376
377// CREATORS
378inline
379TimedSemaphore::TimedSemaphore(bsls::SystemClockType::Enum clockType)
380: d_impl(clockType)
381{
382}
383
384#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
385inline
386TimedSemaphore::TimedSemaphore(const bsl::chrono::system_clock&)
387: d_impl(bsls::SystemClockType::e_REALTIME)
388{
389}
390
391inline
392TimedSemaphore::TimedSemaphore(const bsl::chrono::steady_clock&)
393: d_impl(bsls::SystemClockType::e_MONOTONIC)
394{
395}
396#endif
397
398inline
399TimedSemaphore::TimedSemaphore(int count,
401: d_impl(count, clockType)
402{
403}
404
405#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
406inline
407TimedSemaphore::TimedSemaphore(int count,
408 const bsl::chrono::system_clock&)
409: d_impl(count, bsls::SystemClockType::e_REALTIME)
410{
411}
412
413inline
414TimedSemaphore::TimedSemaphore(int count,
415 const bsl::chrono::steady_clock&)
416: d_impl(count, bsls::SystemClockType::e_MONOTONIC)
417{
418}
419#endif
420
421inline
425
426// MANIPULATORS
427inline
429{
430 d_impl.post();
431}
432
433inline
434void TimedSemaphore::post(int value)
435{
436 d_impl.post(value);
437}
438
439inline
441{
442 return d_impl.timedWait(absTime);
443}
444
445#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
446template <class CLOCK, class DURATION>
447inline
449 const bsl::chrono::time_point<CLOCK, DURATION>& absTime)
450{
451 return bslmt::ChronoUtil::timedWait(this, absTime);
452}
453#endif
454
455inline
457{
458 return d_impl.tryWait();
459}
460
461inline
463{
464 d_impl.wait();
465}
466
467// ACCESSORS
468inline
471{
472 return d_impl.clockType();
473}
474
475} // close package namespace
476
477
478#endif
479
480// ----------------------------------------------------------------------------
481// Copyright 2023 Bloomberg Finance L.P.
482//
483// Licensed under the Apache License, Version 2.0 (the "License");
484// you may not use this file except in compliance with the License.
485// You may obtain a copy of the License at
486//
487// http://www.apache.org/licenses/LICENSE-2.0
488//
489// Unless required by applicable law or agreed to in writing, software
490// distributed under the License is distributed on an "AS IS" BASIS,
491// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
492// See the License for the specific language governing permissions and
493// limitations under the License.
494// ----------------------------- END-OF-FILE ----------------------------------
495
496/** @} */
497/** @} */
498/** @} */
Definition bslmt_timedsemaphore.h:211
Definition bslmt_timedsemaphore.h:222
void post()
Atomically increment the count of this timed semaphore.
Definition bslmt_timedsemaphore.h:428
~TimedSemaphore()
Destroy this timed semaphore.
Definition bslmt_timedsemaphore.h:422
@ e_TIMED_OUT
Definition bslmt_timedsemaphore.h:236
bsls::SystemClockType::Enum clockType() const
Return the clock type used for timeouts.
Definition bslmt_timedsemaphore.h:470
void wait()
Definition bslmt_timedsemaphore.h:462
int tryWait()
Definition bslmt_timedsemaphore.h:456
int timedWait(const bsls::TimeInterval &absTime)
Definition bslmt_timedsemaphore.h:440
Definition bsls_timeinterval.h:307
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition bslmt_barrier.h:344
Definition bdlt_iso8601util.h:707
Enum
Definition bsls_systemclocktype.h:119
@ e_REALTIME
Definition bsls_systemclocktype.h:122