BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslmt_once.h
Go to the documentation of this file.
1/// @file bslmt_once.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslmt_once.h -*-C++-*-
8#ifndef INCLUDED_BSLMT_ONCE
9#define INCLUDED_BSLMT_ONCE
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslmt_once bslmt_once
15/// @brief Provide a thread-safe way to execute code once per process.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslmt
19/// @{
20/// @addtogroup bslmt_once
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslmt_once-purpose"> Purpose</a>
25/// * <a href="#bslmt_once-classes"> Classes </a>
26/// * <a href="#bslmt_once-description"> Description </a>
27/// * <a href="#bslmt_once-warning"> Warning </a>
28/// * <a href="#bslmt_once-thread-safety"> Thread Safety </a>
29/// * <a href="#bslmt_once-usage"> Usage </a>
30/// * <a href="#bslmt_once-first-implementation"> First Implementation </a>
31/// * <a href="#bslmt_once-second-implementation"> Second Implementation </a>
32/// * <a href="#bslmt_once-third-implementation"> Third Implementation </a>
33/// * <a href="#bslmt_once-fourth-implementation"> Fourth Implementation </a>
34/// * <a href="#bslmt_once-using-the-semaphore-implementations"> Using the Semaphore Implementations </a>
35///
36/// # Purpose {#bslmt_once-purpose}
37/// Provide a thread-safe way to execute code once per process.
38///
39/// # Classes {#bslmt_once-classes}
40///
41/// - bslmt::Once: Gate-keeper for code executed only once per process
42/// - bslmt::OnceGuard: Guard class for safely using `bslmt::Once`
43///
44/// @see bslmt_qlock
45///
46/// # Description {#bslmt_once-description}
47/// This component provides a pair of classes, `bslmt::Once` and
48/// `bslmt::OnceGuard`, which give the caller a way to run a body of code
49/// exactly once within the current process, particularly in the presence of
50/// multiple threads. This component also defines the macro `BSLMT_ONCE_DO`,
51/// which provides syntactic sugar to make one-time execution nearly fool-proof.
52/// A common use of one-time execution is the initialization of singletons on
53/// first use.
54///
55/// The `bslmt::Once` class is designed to be statically allocated and
56/// initialized using the `BSLMT_ONCE_INITIALIZER` macro. Client code may use
57/// the `bslmt::Once` object in one of two ways:
58/// 1. it may use the `callOnce` method to call a function or functor
59/// 2. it may call the `enter` and `leave` methods just before and after the
60/// code that is intended to be executed only once.
61/// That code must be executed conditionally on `enter` returning `true`,
62/// indicating that the caller is the first thread to pass through this region
63/// of code. The `leave` method must be executed at the end of the code region,
64/// indicating that the one-time execution has completed and unblocking any
65/// threads waiting on `enter`.
66///
67/// A safer way to use the `enter` and `leave` methods of `bslmt::Once` is to
68/// manage the `bslmt::Once` object using a `bslmt::OnceGuard` object
69/// constructed from the `bslmt::Once` object. Calling `enter` on the
70/// `bslmt::OnceGuard` object will call `enter` on its associated `bslmt::Once`
71/// object. If the call to `enter` returns `true`, then the destructor for the
72/// guard will automatically call `leave` on its associated `bslmt::Once`
73/// object. The `bslmt::OnceGuard` class is intended to be allocated on the
74/// stack (i.e., as a local variable) so that it is automatically destroyed at
75/// the end of its enclosing block. Thus, the to call `leave` of the
76/// `bslmt::Once` object is enforced by the compiler.
77///
78/// An even easier way to use the facilities of this component is to use the
79/// `BSLMT_ONCE_DO` macro. This macro behaves like an `if` statement --
80/// executing the following [compound] statement the first time the control
81/// passes through it in the course of a program's execution, and blocking other
82/// calling threads until the [compound] statement is executed the first time.
83/// Thus, bracketing arbitrary code in a `BSLMT_ONCE_DO` construct is the
84/// easiest way to ensure that code will be executed only once for a program.
85/// The `BSLMT_ONCE_DO` behaves correctly even if there are `return` statements
86/// within the one-time code block.
87///
88/// The implementation of this component uses appropriate memory barriers so
89/// that changes made in the one-time execution code are immediately visible to
90/// all threads at the end of the one-time code block.
91///
92/// ## Warning {#bslmt_once-warning}
93///
94///
95/// The `BSLMT_ONCE_DO` macro consists of a declaration and a `for` loop.
96/// Consequently, the following is syntactically incorrect:
97/// @code
98/// if (xyz) BSLMT_ONCE_DO { stuff() }
99/// @endcode
100/// Also, a `break` or `continue` statement within a `BSLMT_ONCE_DO` construct
101/// terminates the `BSLMT_ONCE_DO`, not a surrounding loop or `switch`
102/// statement. For example:
103/// @code
104/// switch (xyz) {
105/// case 0: BSLMT_ONCE_DO { stuff(); break; /* does not break case */ }
106/// case 1: // Oops! case 0 falls through to here.
107/// }
108/// @endcode
109///
110/// ## Thread Safety {#bslmt_once-thread-safety}
111///
112///
113/// Objects of the `bslmt::Once` class are intended to be shared among threads
114/// and may be accessed and modified simultaneously in multiple threads by using
115/// the methods provided. To allow static initialization, `bslmt::Once` is a
116/// POD type with public member variables. It is not safe to directly access or
117/// manipulate its member variables (including object initialization)
118/// simultaneously from multiple threads. (Note that static initialization
119/// takes place before multiple threading begins, and is thus safe.)
120///
121/// The `bslmt::OnceGuard` objects are designed to be used only by their creator
122/// threads and are typically created on the stack. It is not safe to use a
123/// `bslmt::OnceGuard` by a thread other than its creator.
124///
125/// ## Usage {#bslmt_once-usage}
126///
127///
128/// Typically, the facilities in this component are used to implement a
129/// thread-safe singleton. Below, we implement the a singleton four ways,
130/// illustrating the two ways to directly use `bslmt::Once`, the use of
131/// `bslmt::OnceGuard`, and the use of `BSLMT_ONCE_DO`. In each example, the
132/// singleton functions take a C-string (`const char*`) argument and return a
133/// reference to a `bsl::string` object constructed from the input string. Only
134/// the first call to each singleton function affect the contents of the
135/// singleton string. (The argument is ignored on subsequent calls.)
136///
137/// ### First Implementation {#bslmt_once-first-implementation}
138///
139///
140/// Our first implementation uses the `BSLMT_ONCE_DO` construct, the
141/// recommended way to use this component. The function is a variation of the
142/// singleton pattern described by Scott Meyers, except that the `BSLMT_ONCE_DO`
143/// macro is used to handle multiple entries to the function in a thread-safe
144/// manner:
145/// @code
146/// const bsl::string& singleton0(const char *s)
147/// {
148/// static bsl::string *theSingletonPtr = 0;
149/// BSLMT_ONCE_DO {
150/// static bsl::string theSingleton(s,
151/// bslma::Default::globalAllocator());
152/// theSingletonPtr = &theSingleton;
153/// }
154/// return *theSingletonPtr;
155/// }
156/// @endcode
157/// The `BSLMT_ONCE_DO` mechanism suffices for most situations; however, if more
158/// flexibility is required, review the remaining examples in this series for
159/// more design choices. The next example will use the lowest-level facilities
160/// of `bslmt::Once`. The two following examples use progressively higher-level
161/// facilities to produce simpler singleton implementations (though none as
162/// simple as the `BSLMT_ONCE_DO` example above).
163///
164/// ### Second Implementation {#bslmt_once-second-implementation}
165///
166///
167/// The next singleton function implementation directly uses the `doOnce` method
168/// of `bslmt::Once`. We begin by declaring a functor type that does most of
169/// the work of the singleton, i.e., constructing the string and setting a
170/// (static) pointer to the string:
171/// @code
172/// static bsl::string *theSingletonPtr = 0;
173///
174/// class SingletonInitializer {
175/// const char *d_initialValue;
176///
177/// public:
178/// SingletonInitializer(const char *initialValue)
179/// : d_initialValue(initialValue)
180/// {
181/// }
182///
183/// void operator()() const {
184/// static bsl::string theSingleton(d_initialValue);
185/// theSingletonPtr = &theSingleton;
186/// }
187/// };
188/// @endcode
189/// The function call operator of the type above is *not* thread-safe. Firstly,
190/// many threads might attempt to simultaneously construct the `theSingleton`
191/// object. Secondly, once `theSingletonPtr` is set by one thread, other
192/// threads still might not see the change (and try to initialize the singleton
193/// again).
194///
195/// The `singleton1` function, below, invokes `SingletonInitializer::operator()`
196/// via the `callOnce` method of `bslmt::Once` to ensure that `operator()` is
197/// called by only one thread and that the result is visible to all threads. We
198/// start by creating and initializing a static object of type `bslmt::Once`:
199/// @code
200/// const bsl::string& singleton1(const char *s)
201/// {
202/// static bslmt::Once once = BSLMT_ONCE_INITIALIZER;
203/// @endcode
204/// We construct a `SingletonInitializer` instance, effectively "binding" the
205/// argument `s` so that it may be used in a function invoked by `callOnce`,
206/// which takes only a no-argument functor (or function). The first thread (and
207/// only the first thread) entering this section of code will set `theSingleton`.
208/// @code
209/// once.callOnce(SingletonInitializer(s));
210/// return *theSingletonPtr;
211/// }
212/// @endcode
213/// Once we return from `callOnce`, the appropriate memory barrier has been
214/// executed so that the change to `theSingletonPtr` is visible to all threads.
215/// A thread calling `callOnce` after the initialization has completed would
216/// immediately return from the call. A thread calling `callOnce` while
217/// initialization is still in progress would block until initialization
218/// completes and then return.
219///
220/// *Implementation* *Note*: As an optimization, developers sometimes pre-check
221/// the value to be set, `theSingletonPtr` in this case, to avoid (heavy) memory
222/// barrier operations; however, that practice is not recommended here. First,
223/// the value of the string may be cached by a different CPU, even though the
224/// pointer has already been updated on the common memory bus. Second, The
225/// implementation of the `callOnce` method is fast enough that a pre-check
226/// would not provide any performance benefit.
227///
228/// The one advantage of this implementation over the previous one is that an
229/// exception thrown from within `singletonImp` will cause the `bslmt::Once`
230/// object to be restored to its original state, so that the next entry into the
231/// singleton will retry the operation.
232///
233/// ### Third Implementation {#bslmt_once-third-implementation}
234///
235///
236/// Our next implementation, `singleton2`, eliminates the need for the
237/// `singletonImp` function and thereby does away with the use of the
238/// a functor type to "bind" the initialization parameter; however, it does
239/// require use of `bslmt::Once::OnceLock`, created on each thread's stack and
240/// passed to the methods of `bslmt::Once`. First, we declare a static
241/// `bslmt::Once` object as before, and also declare a static pointer to
242/// `bsl::string`:
243/// @code
244/// const bsl::string& singleton2(const char *s)
245/// {
246/// static bslmt::Once once = BSLMT_ONCE_INITIALIZER;
247/// static bsl::string *theSingletonPtr = 0;
248/// @endcode
249/// Next, we define a local `bslmt::Once::OnceLock` object and pass it to the
250/// `enter` method:
251/// @code
252/// bslmt::Once::OnceLock onceLock;
253/// if (once.enter(&onceLock)) {
254/// @endcode
255/// If the `enter` method returns `true`, we proceed with the initialization of
256/// the singleton, as before.
257/// @code
258/// static bsl::string theSingleton(s);
259/// theSingletonPtr = &theSingleton;
260/// @endcode
261/// When initialization is complete, the `leave` method is called for the same
262/// context cookie previously used in the call to `enter`:
263/// @code
264/// once.leave(&onceLock);
265/// }
266/// @endcode
267/// When any thread reaches this point, initialization has been complete and
268/// initialized string is returned:
269/// @code
270/// return *theSingletonPtr;
271/// }
272/// @endcode
273///
274/// ### Fourth Implementation {#bslmt_once-fourth-implementation}
275///
276///
277/// Our final implementation, `singleton3`, uses `bslmt::OnceGuard` to simplify
278/// the previous implementation by using `bslmt::OnceGuard` to hide (automate)
279/// the use of `bslmt::Once::OnceLock`. We begin as before, defining a static
280/// `bslmt::Once` object and a static `bsl::string` pointer:
281/// @code
282/// const bsl::string& singleton3(const char *s)
283/// {
284/// static bslmt::Once once = BSLMT_ONCE_INITIALIZER;
285/// static bsl::string *theSingletonPtr = 0;
286/// @endcode
287/// We then declare a local `bslmt::OnceGuard` object and associate it with the
288/// `bslmt::Once` object before entering the one-time initialization region:
289/// @code
290/// bslmt::OnceGuard onceGuard(&once);
291/// if (onceGuard.enter()) {
292/// static bsl::string theSingleton(s);
293/// theSingletonPtr = &theSingleton;
294/// }
295/// return *theSingletonPtr;
296/// }
297/// @endcode
298/// Note that it is unnecessary to call `onceGuard.leave()` because that is
299/// called automatically before the function returns. This machinery makes the
300/// code more robust in the presence of, e.g., return statements in the
301/// initialization code.
302///
303/// If there is significant code after the end of the one-time initialization,
304/// the guard and the initialization code should be enclosed in an extra block
305/// so that the guard is destroyed as soon as validly possible and allow other
306/// threads waiting on the initialization to continue. Alternatively, one can
307/// call `onceGuard.leave()` explicitly at the end of the initialization.
308///
309/// ### Using the Semaphore Implementations {#bslmt_once-using-the-semaphore-implementations}
310///
311///
312/// The following pair of functions, `thread1func` and `thread2func` which will
313/// be run by different threads:
314/// @code
315/// void *thread1func(void *)
316/// {
317/// const bsl::string& s0 = singleton0("0 hello");
318/// const bsl::string& s1 = singleton1("1 hello");
319/// const bsl::string& s2 = singleton2("2 hello");
320/// const bsl::string& s3 = singleton3("3 hello");
321///
322/// assert('0' == s0[0]);
323/// assert('1' == s1[0]);
324/// assert('2' == s2[0]);
325/// assert('3' == s3[0]);
326///
327/// // ... lots more code goes here
328/// return 0;
329/// }
330///
331/// void *thread2func(void *)
332/// {
333/// const bsl::string& s0 = singleton0("0 goodbye");
334/// const bsl::string& s1 = singleton1("1 goodbye");
335/// const bsl::string& s2 = singleton2("2 goodbye");
336/// const bsl::string& s3 = singleton3("3 goodbye");
337///
338/// assert('0' == s0[0]);
339/// assert('1' == s1[0]);
340/// assert('2' == s2[0]);
341/// assert('3' == s3[0]);
342///
343/// // ... lots more code goes here
344/// return 0;
345/// }
346/// @endcode
347/// Both threads attempt to initialize the four singletons. In our example,
348/// each thread passes a distinct argument to the singleton, allowing us to
349/// identify the thread that initializes the singleton. (In practice, the
350/// arguments passed to a specific singleton are almost always fixed and most
351/// singletons don't take arguments at all.)
352///
353/// Assuming that the first thread function wins all of the races to initialize
354/// the singletons, the first singleton is set to "0 hello", the second
355/// singleton to "1 hello", etc.
356/// @code
357/// int usageExample1()
358/// {
359/// void startThread1();
360/// void startThread2();
361///
362/// startThread1();
363/// startThread2();
364///
365/// assert(singleton0("0") == "0 hello");
366/// assert(singleton1("1") == "1 hello");
367/// assert(singleton2("2") == "2 hello");
368/// assert(singleton3("3") == "3 hello");
369///
370/// return 0;
371/// }
372/// @endcode
373/// @}
374/** @} */
375/** @} */
376
377/** @addtogroup bsl
378 * @{
379 */
380/** @addtogroup bslmt
381 * @{
382 */
383/** @addtogroup bslmt_once
384 * @{
385 */
386
387#include <bslscm_version.h>
388
389#include <bslmt_qlock.h>
390
392#include <bsls_assert.h>
393#include <bsls_buildtarget.h>
394#include <bsls_performancehint.h>
395#include <bsls_platform.h>
396
397#include <bsl_exception.h>
398
399
400
401#if defined(BSLS_PLATFORM_CMP_MSVC)
402# define BSLMT_ONCE_UNIQNUM __COUNTER__
403 // MSVC: The '__LINE__' macro breaks when '/ZI' is used (see Q199057 or
404 // KB199057). Fortunately the '__COUNTER__' extension provided by MSVC
405 // is even better.
406#else
407# define BSLMT_ONCE_UNIQNUM __LINE__
408#endif
409
410/// This macro provides a simple control construct to bracket a piece of
411/// code that should only be executed once during the course of a
412/// multithreaded program. Usage:
413/// @code
414/// BSLMT_ONCE_DO { /* one-time code goes here */ }
415/// @endcode
416/// Leaving a `BSLMT_ONCE_DO` construct via `break`, `continue`, or `return`
417/// will put the construct in a "done" state (unless `BSLMT_ONCE_CANCEL` has
418/// been called) and will unblock all threads waiting to enter the one-time region.
419///
420/// \note Note that a `break` or `continue` within the one-time code will
421/// terminate only the `BSLMT_ONCE_DO` construct, not any surrounding loop
422/// or switch statement. Due to a bug in the Microsoft Visual C++ 2003
423/// compiler, the behavior is undefined if an exception is thrown from
424/// within this construct and is not caught within the same construct. Only
425/// one call to `BSLMT_ONCE_DO` may appear on a single source-code line in
426/// any code block.
427#define BSLMT_ONCE_DO \
428 BSLMT_ONCE_DO_IMP(BSLMT_ONCE_CAT(bslmt_doOnceObj, BSLMT_ONCE_UNIQNUM))
429
430/// This macro provides a way to cancel once processing within a
431/// `BSLMT_ONCE_DO` construct. It will not compile outside of a
432/// `BSLMT_ONCE_DO` construct. Executing this function-like macro will set
433/// the state of the `BSLMT_ONCE_DO` construct to "not entered", possibly
434/// unblocking a thread waiting to enter the one-time code region.
435///
436/// \note Note that this macro does not exit the `BSLMT_ONCE_DO` construct (i.e., it
437/// does not have `break` or `return` semantics).
438#define BSLMT_ONCE_CANCEL() bslmt_doOnceGuard.cancel()
439
440/// Use this macro to initialize an object of type `Once`. E.g.:
441/// @code
442/// Once once = BSLMT_ONCE_INITIALIZER;
443/// @endcode
444#define BSLMT_ONCE_INITIALIZER { BSLMT_QLOCK_INITIALIZER, { 0 } }
445
446namespace bslmt {
447
448 // ==========
449 // class Once
450 // ==========
451
452/// Gate-keeper class for code that should only execute once per process.
453/// This class is a POD-type and can be statically initialized to the value
454/// of the `BSLMT_ONCE_INITIALIZE` macro. For this reason, it does not have
455/// any explicitly-declared constructors or destructor.
456///
457/// See @ref bslmt_once
458class Once {
459
460 // PRIVATE TYPES
461 enum { e_NOT_ENTERED, e_IN_PROGRESS, e_DONE };
462
463 private:
464 // NOT IMPLEMENTED
465
466 /// Copy-assignment is not allowed. We cannot declare a private copy
467 /// constructor because that would make this class a non-POD.
468 Once& operator=(const Once&);
469
470 public:
471 // These variables are public so that this (POD) type can be statically
472 // initialized. Do not access these variables directly.
473
474 // DATA
476 // public, but do *not* access directly
477 bsls::AtomicOperations::AtomicTypes::Int d_state;
478 // public, but do *not* access directly
479
480 public:
481 // PUBLIC TYPES
482
483 /// Special token created by a single thread to pass to the `enter`,
484 /// `leave`, and `cancel` methods.
486
487 // MANIPULATORS
488
489 /// Lock the internal mutex using the specified `onceLock` (possibly
490 /// blocking if another thread has already locked the mutex). If no
491 /// other thread has yet called `enter` or `callOnce` on this object,
492 /// return `true`. Otherwise, unlock the mutex and return `false`. The
493 /// mutex lock may be skipped if it can be determined that it will not be needed.
494 ///
495 /// \pre The behavior is undefined if `onceLock` is already in a locked state on entry to this method.
496 ///
497 /// \note Note that if `enter` returns
498 /// `true`, the caller *must* eventually call `leave`, or else other
499 /// threads may block indefinitely.
500 bool enter(OnceLock *onceLock);
501
502 /// Set this object into a state such that pending and future calls to
503 /// `enter` or `callOnce` will return `false` or do nothing,
504 /// respectively, then unlock the internal mutex using the specified
505 /// `onceLock` (possibly unblocking pending calls to `enter` or `callOnce`).
506 ///
507 /// \pre The behavior is undefined unless `onceLock` was locked
508 /// by a matching call to `enter` on this object and has not been
509 /// tampered-with since.
510 void leave(OnceLock *onceLock);
511
512 /// Revert this object to the state it was in before `enter` or
513 /// `callOnce` was called, then unlock the internal mutex using the
514 /// specified `onceLock` (possibly unblocking pending calls to `enter`
515 /// or `callOnce`). This method may only be used to cancel execution of
516 /// one-time code that has not yet completed.
517 ///
518 /// \pre The behavior is undefined unless `onceLock` was locked by a matching call to `enter` on this
519 /// object and has not been tampered-with since (especially by calling
520 /// `leave`).
521 void cancel(OnceLock *onceLock);
522
523 /// If no other thread has yet called `enter` or `callOnce`, then call
524 /// the specified `function` and set this object to the state where
525 /// pending and future calls to `enter` or `callOnce` will return
526 /// `false` or do nothing, respectively. Otherwise, wait for the
527 /// one-time code to complete and return without calling `function`
528 /// where `function` is a function or functor that can be called with no arguments.
529 ///
530 /// \note Note that one-time code is considered not to have run if
531 /// `function` terminates with an exception.
532 template <class FUNC>
533 void callOnce(FUNC& function);
534 template <class FUNC>
535 void callOnce(const FUNC& function);
536
537 // ACCESSORS
538
539 /// Return `true` if this object may not be in the "done" state (that
540 /// is, `leave` has not been called).
541 bool isMaybeUninitialized() const;
542};
543
544 // ===============
545 // class OnceGuard
546 // ===============
547
548/// Guard class for using `Once` safely. Construct an object of this class
549/// before conditionally entering one-time processing code. Destroy the object
550/// when the one-time code is complete. When used this way, this object will
551/// be in an "in-progress" state during the time that the one-time code is
552/// being executed.
553///
554/// See @ref bslmt_once
556
557 // PRIVATE TYPES
558 enum State { e_NOT_ENTERED, e_IN_PROGRESS, e_DONE };
559
560 // DATA
561 Once::OnceLock d_onceLock;
562 Once *d_once;
563 State d_state;
564 int d_num_exceptions; // exceptions active at construction
565
566 private:
567 // NOT IMPLEMENTED
568 OnceGuard(const OnceGuard&);
569 OnceGuard& operator=(const OnceGuard&);
570
571 public:
572 // CREATORS
573
574 /// Initialize this object to guard the (optionally) specified `once`
575 /// object. If `once` is not specified, then it must be set later using
576 /// the `setOnce` method before other methods may be called.
577 explicit OnceGuard(Once *once = 0);
578
579 /// Destroy this object. If this object is not in an "in-progress" state,
580 /// do nothing. If this object is in an "in-progress" state and is being
581 /// destroyed in the course of normal processing, then call `leave` on the
582 /// associated `Once` object.
584
585 // MANIPULATORS
586
587 /// Set this object to guard the specified `once` object.
588 ///
589 /// \pre The behavior is undefined if this object is currently in the "in-progress" state.
590 void setOnce(Once *once);
591
592 /// Call `enter` on the associated `Once` object and return the result. If
593 /// `Once::enter` returns `true`, set this object into the "in-progress" state.
594 ///
595 /// \pre The behavior is undefined unless this object has been
596 /// associated with a `Once` object, either in the constructor or using
597 /// `setOnce`, or if this object is already in the "in-progress" state.
598 bool enter();
599
600 /// If this object is in the "in-progress" state, call `leave` on the
601 /// associated `Once` object and exit the "in-progress" state. Otherwise,
602 /// do nothing.
603 void leave();
604
605 /// If this object is in the "in-progress" state, call `cancel` on the
606 /// associated `Once` object and exit the "in-progress" state. Otherwise,
607 /// do nothing.
608 void cancel();
609
610 // ACCESSORS
611
612 /// Return `true` if this object is in the "in-progress" state. The object
613 /// is in-progress if `enter` has been called and returned `true` and
614 /// neither `leave` nor `cancel` have been called. The one-time code
615 /// controlled by this object should only be executing if this object is in
616 /// the "in-progress" state.
617 bool isInProgress() const;
618};
619
620// ============================================================================
621// INLINE DEFINITIONS
622// ============================================================================
623
624 // ----------------------------------
625 // Token concatenation support macros
626 // ----------------------------------
627
628// Second layer needed to ensure that arguments are expanded before
629// concatenation.
630#define BSLMT_ONCE_CAT(X, Y) BSLMT_ONCE_CAT_IMP(X, Y)
631#define BSLMT_ONCE_CAT_IMP(X, Y) X##Y
632
633 // -------------------------------------
634 // Implementation of BSLMT_ONCE_DO Macro
635 // -------------------------------------
636
637// Use a for-loop to initialize the guard, test if we can enter the
638// once-region, then leave the once-region at the end. Each invocation of this
639// macro within a source file supplies a different `doOnceObj` name.
640#define BSLMT_ONCE_DO_IMP(doOnceObj) \
641 static BloombergLP::bslmt::Once doOnceObj = BSLMT_ONCE_INITIALIZER; \
642 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( /* NOLINT */\
643 doOnceObj.isMaybeUninitialized())) \
644 for (BloombergLP::bslmt::OnceGuard /* NOLINT */\
645 bslmt_doOnceGuard(&doOnceObj);\
646 bslmt_doOnceGuard.enter(); bslmt_doOnceGuard.leave())
647
648 // ---------------
649 // class OnceGuard
650 // ---------------
651
652// CREATORS
653inline
654OnceGuard::OnceGuard(Once *once)
655: d_once(once)
656, d_state(e_NOT_ENTERED)
657, d_num_exceptions(bsl::uncaught_exceptions())
658{
659}
660
661// MANIPULATORS
662inline
664{
665 BSLS_ASSERT_SAFE(e_IN_PROGRESS != d_state);
666
667 d_once = once;
668 d_state = e_NOT_ENTERED;
669}
670
671// ACCESSORS
672inline
674{
675 return e_IN_PROGRESS == d_state;
676}
677
678 // ----------
679 // class Once
680 // ----------
681
682// MANIPULATORS
683template <class FUNC>
684inline
685void Once::callOnce(FUNC& function)
686{
687 OnceGuard guard(this);
688 if (guard.enter()) {
689#ifdef BDE_BUILD_TARGET_EXC
690 try {
691 function();
692 }
693 catch (...) {
694 guard.cancel();
695 throw;
696 }
697#else
698 function();
699#endif
700 }
701}
702
703template <class FUNC>
704inline
705void Once::callOnce(const FUNC& function)
706{
707 OnceGuard guard(this);
708 if (guard.enter()) {
709#ifdef BDE_BUILD_TARGET_EXC
710 try {
711 function();
712 }
713 catch (...) {
714 guard.cancel();
715 throw;
716 }
717#else
718 function();
719#endif
720 }
721}
722
723// ACCESSORS
724inline
726{
728}
729
730} // close package namespace
731
732
733#if !defined(BSL_DOUBLE_UNDERSCORE_XLAT) || 1 == BSL_DOUBLE_UNDERSCORE_XLAT
734#define BSLMT_ONCE__CAT(X, Y) BSLMT_ONCE_CAT(X, Y)
735#endif
736
737#endif
738
739// ----------------------------------------------------------------------------
740// Copyright 2015 Bloomberg Finance L.P.
741//
742// Licensed under the Apache License, Version 2.0 (the "License");
743// you may not use this file except in compliance with the License.
744// You may obtain a copy of the License at
745//
746// http://www.apache.org/licenses/LICENSE-2.0
747//
748// Unless required by applicable law or agreed to in writing, software
749// distributed under the License is distributed on an "AS IS" BASIS,
750// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
751// See the License for the specific language governing permissions and
752// limitations under the License.
753// ----------------------------- END-OF-FILE ----------------------------------
754
755/** @} */
756/** @} */
757/** @} */
Definition bslmt_once.h:555
bool isInProgress() const
Definition bslmt_once.h:673
void setOnce(Once *once)
Definition bslmt_once.h:663
Definition bslmt_once.h:458
QLock d_mutex
Definition bslmt_once.h:475
bool enter(OnceLock *onceLock)
bool isMaybeUninitialized() const
Definition bslmt_once.h:725
void leave(OnceLock *onceLock)
void callOnce(FUNC &function)
Definition bslmt_once.h:685
bsls::AtomicOperations::AtomicTypes::Int d_state
Definition bslmt_once.h:477
void cancel(OnceLock *onceLock)
QLockGuard OnceLock
Definition bslmt_once.h:485
Definition bslmt_qlock.h:388
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1917
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition bdlat_valuetypefunctions.h:939
Definition bslmt_barrier.h:344
Definition bslmt_qlock.h:273
static int getIntAcquire(AtomicTypes::Int const *atomicInt)
Definition bsls_atomicoperations.h:1530