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