BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bsls_atomic.h
Go to the documentation of this file.
1/// @file bsls_atomic.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bsls_atomic.h -*-C++-*-
8#ifndef INCLUDED_BSLS_ATOMIC
9#define INCLUDED_BSLS_ATOMIC
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bsls_atomic bsls_atomic
15/// @brief Provide types with atomic operations.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bsls
19/// @{
20/// @addtogroup bsls_atomic
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bsls_atomic-purpose"> Purpose</a>
25/// * <a href="#bsls_atomic-classes"> Classes </a>
26/// * <a href="#bsls_atomic-description"> Description </a>
27/// * <a href="#bsls_atomic-memory-order-and-consistency-guarantees-of-atomic-operations"> Memory Order and Consistency Guarantees of Atomic Operations </a>
28/// * <a href="#bsls_atomic-acquire-and-release-memory-consistency-guarantees"> Acquire and Release Memory Consistency Guarantees </a>
29/// * <a href="#bsls_atomic-sequential-consistency-memory-consistency-guarantee"> Sequential Consistency Memory Consistency Guarantee </a>
30/// * <a href="#bsls_atomic-usage"> Usage </a>
31/// * <a href="#bsls_atomic-example-1-usage-statistics-on-a-thread-pool"> Example 1: Usage Statistics on a Thread Pool </a>
32/// * <a href="#bsls_atomic-example-2-thread-safe-counted-handle"> Example 2: Thread-Safe Counted Handle </a>
33/// * <a href="#bsls_atomic-class-my_countedhandlerep"> Class my_CountedHandleRep </a>
34/// * <a href="#bsls_atomic-class-my_countedhandle"> Class my_CountedHandle </a>
35/// * <a href="#bsls_atomic-function-definitions-for-my_countedhandlerep"> Function Definitions for my_CountedHandleRep </a>
36/// * <a href="#bsls_atomic-function-definitions-for-my_countedhandle"> Function Definitions for my_CountedHandle </a>
37/// * <a href="#bsls_atomic-example-3-thread-safe-lock-free-singly-linked-list"> Example 3: Thread-Safe Lock-Free Singly-Linked List </a>
38///
39/// # Purpose {#bsls_atomic-purpose}
40/// Provide types with atomic operations.
41///
42/// # Classes {#bsls_atomic-classes}
43///
44/// - bsls::AtomicBool: atomic boolean type
45/// - bsls::AtomicInt: atomic 32-bit integer type
46/// - bsls::AtomicInt64: atomic 64-bit integer type
47/// - bsls::AtomicUint: atomic 32-bit unsigned integer type
48/// - bsls::AtomicUint64: atomic 64-bit unsigned integer type
49/// - bsls::AtomicPointer: parameterized atomic pointer type
50///
51/// @see bsls_atomicoperations
52///
53/// # Description {#bsls_atomic-description}
54/// This component provides classes with atomic operations for
55/// `int`, `Int64`, `unsigned int`, `Uint64`, `pointer`, and `bool` types.
56/// These classes are based on atomic operations supplied by the
57/// @ref bsls_atomicoperations component. The `bsls::AtomicInt` and
58/// `bsls::AtomicInt64` classes represent the corresponding atomic integer
59/// types, and provide overloaded operators and functions for common arithmetic
60/// operations. The `bsls::AtomicPointer` class represents the atomic pointer
61/// type, and provides atomic operations to manipulate and dereference a
62/// pointer. The `bsls::AtomicBool` class represents an atomic boolean type and
63/// provides operations to set and retrieve its value.
64///
65/// ## Memory Order and Consistency Guarantees of Atomic Operations {#bsls_atomic-memory-order-and-consistency-guarantees-of-atomic-operations}
66///
67///
68/// Atomic operations provided by this component ensure various memory ordering
69/// consistency guarantees. Memory ordering guarantees of atomic operations are
70/// designed to ensure visibility and synchronization order of memory reads and
71/// writes between threads that perform atomic operations. The operations on
72/// objects of the provided classes ensure the most strict consistency
73/// guarantee, sequential consistency (described below), unless explicitly
74/// qualified with a less strict consistency guarantee (i.e., Acquire, Release,
75/// Acquire/Release or Relaxed).
76///
77/// This component implements memory order and consistency guarantees as defined
78/// in the C++ 2011 Standard (sections: [intro.multithreaded], [atomics.order]).
79///
80/// The following memory ordering guarantees are supported:
81///
82/// * relaxed - the operation does not provide any memory consistency guarantee
83/// * release - the operation performs a release operation on the affected
84/// memory location, thus making preceding regular memory writes of the
85/// calling thread visible to other threads through the atomic variable to
86/// which it is applied (generally available for operations that write to a
87/// memory location).
88/// * acquire - the operation performs an acquire operation on the affected
89/// memory location, thus making regular memory writes in other threads
90/// released through the atomic variable to which it is applied visible to
91/// the current thread (generally available for operations that read from a
92/// memory location).
93/// * acquire/release - the operation has both acquire and release semantics
94/// (generally available for operations that both read and write a memory
95/// location).
96/// * sequential consistency - the operation has both acquire and release
97/// guarantees, and further guarantees that all sequentially consistent
98/// operations performed by the process will be observed to occur in a single
99/// global total order (regardless of the thread from which they are
100/// observed).
101///
102/// ### Acquire and Release Memory Consistency Guarantees {#bsls_atomic-acquire-and-release-memory-consistency-guarantees}
103///
104///
105/// Operations providing acquire and release guarantees are essential to
106/// synchronizing the memory state between multiple threads. For example,
107/// consider two threads, A and B, that perform store and load operations to
108/// shared memory locations. Without any synchronization, store operations in
109/// thread A can be freely reordered with load operations in thread B, i.e,
110/// thread A can perform two store operations to two memory locations in a
111/// certain order and thread B can see those operations done in a different
112/// order due to such effects as: compiler or processor optimizations of store
113/// and load operations, and cache synchronization between processors and cores.
114///
115/// However, stores in thread A can be ordered with loads in thread B using a
116/// combination of store-release and load-acquire operations. A store-release
117/// operation in thread A followed by a load-acquire operation in thread B to
118/// the *same* *memory* *location* guarantees that thread B sees all other
119/// stores done in thread A prior to the store-release operation. The
120/// store-release in thread A effectively synchronizes the memory state with the
121/// load-acquire in thread B.
122///
123/// An acquire-release operation is a load-modify-store operation that, if
124/// performed in both threads A and B on the same memory location, synchronizes
125/// stores and loads between threads A and B in both directions.
126///
127/// ### Sequential Consistency Memory Consistency Guarantee {#bsls_atomic-sequential-consistency-memory-consistency-guarantee}
128///
129///
130/// Finally, load and store operations with sequential consistency are
131/// guaranteed to performed in a global total order among all threads in the
132/// process. To illustrate the total order, let's consider the so-called
133/// "independent reads of independent writes" example:
134/// @code
135/// bsls::AtomicInt x(0);
136/// bsls::AtomicInt y(0);
137/// int r1, r2, r3, r4;
138///
139/// void thread1() {
140/// x = 1; // sequential consistency store
141/// }
142///
143/// void thread2() {
144/// y = 1; // sequential consistency store
145/// }
146///
147/// void thread3() {
148/// r1 = x; // sequential consistency load
149/// r2 = y; // sequential consistency load
150/// }
151///
152/// void thread4() {
153/// r3 = y; // sequential consistency load
154/// r4 = x; // sequential consistency load
155/// }
156/// @endcode
157/// Where `threadN` functions are executed concurrently by different threads
158/// (note that values `x` and `y` are written by independent threads).
159/// Sequential consistency guarantees that if `thread3` observes values `x` and
160/// `y` as `r1 == 1 && r2 == 0`, then `thread4` can't observe values `x` and `y`
161/// in a different order, i.e., `r3 == 1 && r4 == 0`.
162///
163/// ## Usage {#bsls_atomic-usage}
164///
165///
166/// This section illustrates intended use of this component.
167///
168/// ### Example 1: Usage Statistics on a Thread Pool {#bsls_atomic-example-1-usage-statistics-on-a-thread-pool}
169///
170///
171/// This example demonstrates a common use of atomic integer types for
172/// statistics counters. The program creates a series of threads to process
173/// transactions. As each thread completes a transaction, it atomically
174/// increments the transaction counters.
175///
176/// For this example, we assume the existence of the functions
177/// `processNextTransaction`, `createWorkerThread`, and `waitAllThreads`. The
178/// function `createWorkerThread` spawns a new thread, which executes the
179/// `workerThread` function. `waitAllThreads` blocks until all the worker
180/// thread complete.
181///
182/// First, we declare the shared counters (note that, in contrast to the raw
183/// types defined in @ref bsls_atomicoperations , these atomic types are
184/// zero-initialized at construction):
185/// @code
186/// static bsls::AtomicInt64 transactionCount;
187/// static bsls::AtomicInt64 successCount;
188/// static bsls::AtomicInt64 failureCount;
189/// @endcode
190/// Next, for each transaction processed, we atomically increment either the
191/// success or the failure counter as well as the total transaction count:
192/// @code
193/// static void workerThread(int *stop)
194/// {
195/// while (!(*stop)) {
196/// if (processNextTransaction()) {
197/// ++failureCount;
198/// } else {
199/// ++successCount;
200/// }
201/// ++transactionCount;
202/// }
203/// }
204/// @endcode
205/// Finally, we write function, `serverMain`, that provides the overall control
206/// logic for the server. This function spawns the threads and then waits for
207/// all work to be completed; when all of the threads have finished, this
208/// function returns normally:
209/// @code
210/// void serverMain()
211/// {
212/// const int num_threads = 10;
213/// for (int i = 0; i < num_threads; ++i) {
214/// createWorkerThread();
215/// }
216/// waitAllThreads();
217/// }
218/// @endcode
219/// Note that functions `createWorkerThread` and `waitAllThreads` can be
220/// implemented using any thread-support package.
221///
222/// ### Example 2: Thread-Safe Counted Handle {#bsls_atomic-example-2-thread-safe-counted-handle}
223///
224///
225/// The following example demonstrates the use of atomic integer operations to
226/// implement a thread-safe ref-counted handle similar to a shared pointer.
227/// Each handle (of type `my_CountedHandle`) maintains a pointer to a
228/// representation object, `my_CountedHandleRep`, which in turn, stores both a
229/// pointer to the managed object and a reference counter.
230///
231/// Both the handle class and the representation class are template classes with
232/// two template parameters. The template parameter, `INSTANCE`, represents the
233/// type of the "instance", or managed object.
234///
235/// A representation object can be shared by several handle objects. When a
236/// handle object is assigned to a second handle object, the address of the
237/// representation is copied to the second handle, and the reference count on
238/// the representation is atomically incremented. When a handle releases its
239/// reference to the representation, it atomically decrements the reference
240/// count. If the resulting reference count becomes 0 (and there are no more
241/// references to the object), the handle deletes the representation object and
242/// the representation object, in turn, deletes the managed object (`INSTANCE`).
243///
244/// ### Class my_CountedHandleRep {#bsls_atomic-class-my_countedhandlerep}
245///
246///
247/// First, we define class `my_CountedHandleRep`. This class manages a single
248/// `INSTANCE` object on behalf of multiple "handle" objects; since different
249/// "handle" objects may be active in different threads, class
250/// `my_CountedHandleRep` must be (fully) thread-safe. Specifically, methods
251/// `increment` and `decrement` must work atomically.
252///
253/// The class declaration for `my_CountedHandleRep` is identical to the same
254/// class in component @ref bsls_atomicoperations , with a single exception: member
255/// `d_count` is of type `bsls::AtomicInt`, rather than
256/// `bsls::AtomicOperations::Int`. Whereas `bsls::AtomicOperations::Int` is
257/// merely a `typedef` for a platform-specific data type to be used in atomic
258/// integer operations, `bsls::AtomicInt` encapsulates those atomic operations
259/// as member functions and operator overloads. Class `my_CountedHandleRep`
260/// will benefit from this encapsulation: Its method implementations will be
261/// able to operate on `d_count` as if it were a standard integer.
262///
263/// Note that, as in the example in component @ref bsls_atomicoperations , this rep
264/// class is intended to be used only by class `my_CountedHandle`, and thus all
265/// methods of class `my_CountedHandleRep` are declared private, and `friend`
266/// status is granted to class `my_CountedHandle`:
267/// @code
268/// // =========================
269/// // class my_CountedHandleRep
270/// // =========================
271///
272/// template <class INSTANCE>
273/// class my_CountedHandle;
274///
275/// template <class INSTANCE>
276/// class my_CountedHandleRep {
277///
278/// // DATA
279/// INSTANCE *d_instance_p; // address of managed instance
280/// bsls::AtomicInt d_count; // number of active references
281///
282/// // FRIENDS
283/// friend class my_CountedHandle<INSTANCE>;
284///
285/// // NOT IMPLEMENTED
286/// my_CountedHandleRep(const my_CountedHandleRep&);
287/// my_CountedHandleRep& operator=(const my_CountedHandleRep&);
288///
289/// private:
290/// // PRIVATE CLASS METHODS
291/// static void
292/// deleteObject(my_CountedHandleRep<INSTANCE> *object);
293///
294/// // PRIVATE CREATORS
295/// my_CountedHandleRep(INSTANCE *instance);
296/// ~my_CountedHandleRep();
297///
298/// // PRIVATE MANIPULATORS
299/// void increment();
300/// int decrement();
301/// };
302/// @endcode
303///
304/// #### Class my_CountedHandle {#bsls_atomic-class-my_countedhandle}
305///
306///
307/// Then, we create class `my_CountedHandle` that provides an individual handle
308/// to the shared, reference-counted object. Each `my_CountedHandle` object
309/// acts as a smart pointer, supplying an overloaded `operator->` that provides
310/// access to the underlying `INSTANCE` object via pointer semantics.
311///
312/// `my_CountedHandle` can also be copied freely; the copy constructor will use
313/// the `increment` method from `my_CountedHandleRep` to note the extra copy.
314/// Similarly, the destructor will call `my_CountedHandleRep::decrement` to note
315/// that there is one fewer handle the underlying `INSTANCE` has, and delete the
316/// "rep" object when its reference count is reduced to zero.
317///
318/// Similar to `my_CountedHandleRep`, the class declaration for
319/// `my_CountedHandle` is identical to that in @ref bsls_atomicoperations :
320/// @code
321/// // ======================
322/// // class my_CountedHandle
323/// // ======================
324///
325/// template <class INSTANCE>
326/// class my_CountedHandle {
327///
328/// // DATA
329/// my_CountedHandleRep<INSTANCE> *d_rep_p; // shared rep.
330///
331/// public:
332/// // CREATORS
333/// my_CountedHandle();
334/// my_CountedHandle(INSTANCE *instance);
335///
336/// my_CountedHandle(const my_CountedHandle<INSTANCE>& other);
337///
338/// ~my_CountedHandle();
339///
340/// // ACCESSORS
341/// INSTANCE *operator->() const;
342/// int numReferences() const;
343/// };
344/// @endcode
345///
346/// #### Function Definitions for my_CountedHandleRep {#bsls_atomic-function-definitions-for-my_countedhandlerep}
347///
348///
349/// Next, we provide a definition for the `static` `deleteObject` method, which
350/// is called by the destructor for class `my_CountedHandle` for the last
351/// instance of `my_CountedHandle` using the given "rep" object:
352/// @code
353/// template <class INSTANCE>
354/// inline
355/// void my_CountedHandleRep<INSTANCE>::deleteObject(
356/// my_CountedHandleRep<INSTANCE> *object)
357/// {
358/// delete object;
359/// }
360/// @endcode
361/// Then, we define the constructor for the `my_CountedHandleRep<INSTANCE>`
362/// class. Member `d_count` is initialized to 1, reflecting the fact that this
363/// constructor will be called by a new instance of `my_CountedHandle`, which
364/// instance is our first and only handle when this constructor is called:
365/// notice that `d_count` (of type `bsls::AtomicInt`) is initialized as if it
366/// were a simple integer; its constructor guarantees that the initialization is
367/// done atomically.
368/// @code
369/// template <class INSTANCE>
370/// inline
371/// my_CountedHandleRep<INSTANCE>:: my_CountedHandleRep(INSTANCE *instance)
372/// : d_instance_p(instance)
373/// , d_count(1)
374/// {
375/// }
376/// @endcode
377/// Then, we define the destructor, which just deletes `my_CountedHandle`
378/// `d_instance_p`:
379/// @code
380/// template <class INSTANCE>
381/// inline
382/// my_CountedHandleRep<INSTANCE>::~my_CountedHandleRep()
383/// {
384/// delete d_instance_p;
385/// }
386/// @endcode
387/// Next, we define method `increment`, which is called by `my_CountedHandle` to
388/// add a new reference to the current "rep" object, which simply increments
389/// `d_count`, using the prefix `operator++`:
390/// @code
391/// // MANIPULATORS
392/// template <class INSTANCE>
393/// inline
394/// void my_CountedHandleRep<INSTANCE>::increment()
395/// {
396/// ++d_count;
397/// }
398/// @endcode
399/// The above operation must be done atomically in a multi-threaded context;
400/// class `bsls::AtomicInt` provides this guarantee for all its overloaded
401/// operators, and `my_CountedHandleRep` relies upon this guarantee.
402///
403/// Then, we implement method `decrement`, which is called by `my_CountedHandle`
404/// when a reference to the current "rep" object is being deleted:
405/// @code
406/// template <class INSTANCE>
407/// inline
408/// int my_CountedHandleRep<INSTANCE>::decrement()
409/// {
410/// return --d_count;
411/// }
412/// @endcode
413/// This method atomically decrements the number of references to this
414/// `my_CountedHandleRep` and, once again, atomicity is guaranteed by the
415/// underlying type of `d_count`.
416///
417/// #### Function Definitions for my_CountedHandle {#bsls_atomic-function-definitions-for-my_countedhandle}
418///
419///
420/// Next, we define the first constructor for `my_CountedHandle`, which is used
421/// when creating a handle for a new `INSTANCE`; note that the `INSTANCE` is
422/// constructed separately, and a pointer to that object is passed as the first
423/// argument (`object`):
424/// @code
425/// // ----------------------
426/// // class my_CountedHandle
427/// // ----------------------
428///
429/// // CREATORS
430/// template <class INSTANCE>
431/// inline
432/// my_CountedHandle<INSTANCE>::my_CountedHandle(INSTANCE *instance)
433/// {
434/// d_rep_p = new my_CountedHandleRep<INSTANCE>(instance);
435/// }
436/// @endcode
437/// Then, we define the copy constructor; the new object copies the underlying
438/// `my_CountedHandleRep` and then increments its counter:
439/// @code
440/// template <class INSTANCE>
441/// inline
442/// my_CountedHandle<INSTANCE>::my_CountedHandle(
443/// const my_CountedHandle<INSTANCE>& other)
444/// : d_rep_p(other.d_rep_p)
445/// {
446/// if (d_rep_p) {
447/// d_rep_p->increment();
448/// }
449/// }
450/// @endcode
451/// Next, we define the destructor that decrements the "rep" object's reference
452/// count using the `decrement` method. The `decrement` method returns the
453/// object's reference count after the decrement is completed, and
454/// `my_CountedHandle` uses this value to determine whether the "rep" object
455/// should be deleted:
456/// @code
457/// template <class INSTANCE>
458/// inline
459/// my_CountedHandle<INSTANCE>::~my_CountedHandle()
460/// {
461/// if (d_rep_p && 0 == d_rep_p->decrement()) {
462/// my_CountedHandleRep<INSTANCE>::deleteObject(d_rep_p);
463/// }
464/// }
465/// @endcode
466/// Now, we define member `operator->()`, which provides basic pointer semantics
467/// for `my_CountedHandle`:
468/// @code
469/// // ACCESSORS
470/// template <class INSTANCE>
471/// inline
472/// INSTANCE *my_CountedHandle<INSTANCE>::operator->() const
473/// {
474/// return d_rep_p->d_instance_p;
475/// }
476/// @endcode
477/// Finally, we define method `numReferences`, which returns the value of the
478/// reference counter:
479/// @code
480/// template <class INSTANCE>
481/// inline
482/// int my_CountedHandle<INSTANCE>::numReferences() const
483/// {
484/// return d_rep_p ? d_rep_p->d_count : 0;
485/// }
486/// @endcode
487/// Note that, while class `my_CountedHandleRep` is itself fully thread-safe, it
488/// does not guarantee thread safety for the `INSTANCE` object. In order to
489/// provide thread safety for the `INSTANCE` in the general case, the "rep"
490/// would need to use a more general concurrency mechanism such as a mutex.
491///
492/// ### Example 3: Thread-Safe Lock-Free Singly-Linked List {#bsls_atomic-example-3-thread-safe-lock-free-singly-linked-list}
493///
494///
495/// This example demonstrates the use of atomic pointers to implement a fast and
496/// thread-aware, singly-linked list. The example class, `my_PtrStack`, is a
497/// templatized pointer stack, supporting `push` and `pop` methods. The class
498/// is implemented using a single-linked list. Nodes in the list are linked
499/// together using atomic operations. Instance of this structure are allocated
500/// using the provided allocator. When nodes are freed, they are cached on a
501/// free list. This free list is also implemented as a single-linked list,
502/// using atomic pointer operations.
503///
504/// This example parallels the third usage example given for component
505/// @ref bsls_atomicoperations , presenting a different implementation of
506/// `my_PtrStack<T>`, with an identical public interface. Note that, where the
507/// @ref bsls_atomicoperations example uses the basic data type
508/// `bsls::AtomicOperations::AtomicTypes::Pointer` for members `d_list` and
509/// `d_freeList`, this implementation uses instead the higher-level type
510/// `bsls::AtomicPointer<T>`.
511///
512/// First, we create class template, `my_PtrStack`, parameterized by `TYPE`.
513/// Instances of this template maintain a list of nodes and a free-node list.
514/// Each node has a pointer to a data item, `d_item_p`, a link to the next node
515/// in the list, `d_next_p` and an atomic flag, `d_inUseFlag`, intended for
516/// lock-free list manipulation. The definition of the `my_PtrStack` class is
517/// provided below:
518/// @code
519/// template <class TYPE>
520/// class my_PtrStack {
521/// // TYPES
522/// struct Node {
523/// TYPE *d_item_p;
524/// Node *d_next_p;
525/// bsls::AtomicInt d_inUseFlag; // used to lock this node
526/// };
527///
528/// // DATA
529/// bsls::AtomicPointer<Node> d_list;
530/// bsls::AtomicPointer<Node> d_freeList;
531///
532/// // PRIVATE MANIPULATORS
533/// Node *allocateNode();
534/// void freeNode(Node *node);
535/// void deleteNodes(Node *node);
536///
537/// public:
538/// // CREATORS
539/// my_PtrStack();
540/// ~my_PtrStack();
541///
542/// // MANIPULATORS
543/// void push(TYPE *item);
544/// TYPE *pop();
545/// };
546/// @endcode
547/// Then, we write a constructor that default-initializes the stack. In the
548/// corresponding example in @ref bsls_atomicoperations , the constructor must also
549/// initialize the atomic pointer `d_freeList`. Since this example uses the
550/// encapsulated type `bsls::AtomicPointer`, initialization of these member
551/// variables is done in their default constructors. Hence, no explicit code is
552/// required in this constructor:
553/// @code
554/// // CREATORS
555/// template <class TYPE>
556/// inline my_PtrStack<TYPE>::my_PtrStack()
557/// {
558/// }
559/// @endcode
560/// Next, we define the `deleteNodes` and the destructor function to delete
561/// nodes that the `my_PtrStack` object owns. Note that we don't need to worry
562/// about the concurrent access to node lists in the destructor, as destructor
563/// can be executed in only a single thread:
564/// @code
565/// template <class TYPE>
566/// inline void my_PtrStack<TYPE>::deleteNodes(Node *node)
567/// {
568/// while (node) {
569/// Node *next = node->d_next_p;
570/// delete node;
571/// node = next;
572/// }
573/// }
574///
575/// template <class TYPE>
576/// inline my_PtrStack<TYPE>::~my_PtrStack()
577/// {
578/// deleteNodes(d_list);
579/// deleteNodes(d_freeList);
580/// }
581/// @endcode
582/// Then, we define method `allocateNode` to get a node from the free list in
583/// the thread-safe manner by leveraging atomic operations to ensure proper
584/// thread synchronization:
585/// @code
586/// // PRIVATE MANIPULATORS
587/// template <class TYPE>
588/// typename my_PtrStack<TYPE>::Node *my_PtrStack<TYPE>::allocateNode()
589/// {
590/// Node *node;
591/// while (1) {
592/// node = d_freeList; // get the current head
593/// if (!node) {
594/// break;
595/// }
596/// @endcode
597/// Next, we try locking the node, and start over if locking fails:
598/// @code
599/// if (node->d_inUseFlag.swapInt(1)) {
600/// continue;
601/// }
602/// @endcode
603/// Then, we atomically modify the head if it has not changed. `testAndSwap`
604/// compares `d_freeList` to `node`, replacing `node` with `node->d_next_p` only
605/// if it matches `d_freeList`. If `d_freeList` did not match `node`, then the
606/// free list has been changed on another thread, between its assignment to the
607/// `node` and the call to `testAndSwap`. If the list head has changed, then
608/// try again:
609/// @code
610/// if (d_freeList.testAndSwap(node, node->d_next_p) == node) {
611/// break;
612/// }
613///
614/// // Unlock the node.
615/// node->d_inUseFlag = 0;
616/// }
617/// @endcode
618/// Next, we allocate a new node if there were no nodes in the free node list:
619/// @code
620/// if (!node) {
621/// node = new Node(); // should allocate with 'd_allocator_p', but
622/// // here we use 'new' directly for simplicity
623/// node->d_inUseFlag = 1;
624/// }
625///
626/// return node;
627/// }
628/// @endcode
629/// Note that the `node` is returned in the locked state and remained locked
630/// until it is added to the free list.
631///
632/// Then, we define the `freeNode` method to add a given `node` to the free
633/// list; `freeNode` also needs to be synchronized using atomic operations:
634/// @code
635/// template <class TYPE>
636/// inline void my_PtrStack<TYPE>::freeNode(Node *node)
637/// {
638/// if (!node) {
639/// return;
640/// }
641///
642/// while (1) {
643/// node->d_next_p = d_freeList;
644/// // Atomically test and swap the head of the list with the
645/// // new node. If the list head has been changed (by another
646/// // thread), try again.
647/// if (d_freeList.testAndSwap(node->d_next_p, node) == node->d_next_p)
648/// {
649/// break;
650/// }
651/// }
652///
653/// // unlock the 'node'
654/// node->d_inUseFlag = 0;
655/// }
656/// @endcode
657/// Now, we begin to define the public "stack-like" interface for `my_PtrStack`.
658/// Note that the `push` method is similar to `freeNode`, except that it assigns
659/// an item value and operates on `d_list`, which maintains the list of active
660/// nodes:
661/// @code
662/// // MANIPULATORS
663/// template <class TYPE>
664/// void my_PtrStack<TYPE>::push(TYPE *item)
665/// {
666/// Node *node = allocateNode();
667/// node->d_item_p = item;
668/// while (1) {
669/// node->d_next_p = d_list;
670/// if (d_list.testAndSwap(node->d_next_p, node) == node->d_next_p) {
671/// break;
672/// }
673/// }
674///
675/// node->d_inUseFlag = 0;
676/// }
677/// @endcode
678/// Finally, we define the `pop` method that removes the node from the top of
679/// active node list, `d_list`, adds it to the free-node list, and returns the
680/// data item contained in the node to the caller:
681/// @code
682/// template <class TYPE>
683/// TYPE *my_PtrStack<TYPE>::pop()
684/// {
685/// Node *node;
686/// while (1) {
687/// node = d_list;
688/// if (!node) {
689/// break;
690/// }
691///
692/// if (node->d_inUseFlag.swapInt(1)) {
693/// continue; // node is locked
694/// }
695///
696/// if (d_list.testAndSwap(node, node->d_next_p) == node) {
697/// break; // node list is being modified in another thread
698/// }
699///
700/// node->d_inUseFlag = 0;
701/// }
702///
703/// TYPE *item = node ? node->d_item_p : 0;
704/// if (node) {
705/// freeNode(node);
706/// }
707/// return item;
708/// }
709/// @endcode
710/// Notice that if the stack was empty, a NULL pointer is returned.
711/// @}
712/** @} */
713/** @} */
714
715/** @addtogroup bsl
716 * @{
717 */
718/** @addtogroup bsls
719 * @{
720 */
721/** @addtogroup bsls_atomic
722 * @{
723 */
724
725#include <bsls_atomicoperations.h>
726#include <bsls_types.h>
727
728
729
730namespace bsls {
731
732 // ===============
733 // class AtomicInt
734 // ===============
735
736/// This class implements an atomic integer, which supports common integer
737/// operations in a way that is guaranteed to be atomic. Operations on
738/// objects of this class provide the sequential consistency memory ordering
739/// guarantee unless explicitly qualified with a less strict consistency
740/// guarantee suffix (i.e., Acquire, Release, AcqRel or Relaxed).
741///
742/// See @ref bsls_atomic
744
745 // DATA
746 AtomicOperations::AtomicTypes::Int d_value;
747
748 private:
749 // NOT IMPLEMENTED
750
751 /// Note that the copy constructor and the copy-assignment operator are
752 /// not implemented because they cannot be done atomically.
753 AtomicInt(const AtomicInt&); // = delete
754 AtomicInt& operator=(const AtomicInt& ); // = delete
755
756 public:
757 // CREATORS
758
759 /// Create an atomic integer object having the default value 0.
760 AtomicInt();
761
762 /// Create an atomic integer object having the specified `value`.
763 AtomicInt(int value);
764
765 ~AtomicInt() = default;
766 // Destroy this atomic integer object.
767
768 // MANIPULATORS
769
770 /// Atomically assign the specified `value` to this object, and return a
771 /// reference offering modifiable access to `this` object.
772 AtomicInt& operator=(int value);
773
774 /// Atomically add the specified `value` to this object, and return the
775 /// resulting value.
776 int operator+=(int value);
777
778 /// Atomically subtract the specified `value` from this object, and
779 /// return the resulting value.
780 int operator-=(int value);
781
782 /// Atomically increment the value of this object by 1 and return the
783 /// resulting value.
784 int operator++();
785
786 /// Atomically increment the value of this object by 1 and return the
787 /// value prior to being incremented.
788 int operator++(int);
789
790 /// Atomically decrement the value of this object by 1 and return the
791 /// resulting value.
792 int operator--();
793
794 /// Atomically decrement the value of this object by 1 and return the
795 /// value prior to being decremented.
796 int operator--(int);
797
798 /// Atomically add the specified `value` to this object and return the
799 /// resulting value.
800 int add(int value);
801
802 /// Atomically add the specified `value` to this object and return the
803 /// resulting value, providing the acquire/release memory ordering
804 /// guarantee.
805 int addAcqRel(int value);
806
807 /// Atomically add the specified `value` to this object and return the
808 /// resulting value, providing the relaxed memory ordering guarantee.
809 int addRelaxed(int value);
810
811 /// Atomically assign the specified `value` to this object, providing
812 /// the sequential consistency memory ordering guarantee.
813 void store(int value);
814
815 /// Atomically assign the specified `value` to this object, providing
816 /// the relaxed memory ordering guarantee.
817 void storeRelaxed(int value);
818
819 /// Atomically assign the specified `value` to this object, providing
820 /// the release memory ordering guarantee.
821 void storeRelease(int value);
822
823 /// Atomically subtract the specified `value` to this object and return
824 /// the resulting value.
825 int subtract(int value);
826
827 /// Atomically subtract the specified `value` to this object and return
828 /// the resulting value, providing the acquire/release memory ordering
829 /// guarantee.
830 int subtractAcqRel(int value);
831
832 /// Atomically subtract the specified `value` to this object and return
833 /// the resulting value, providing the relaxed memory ordering
834 /// guarantee.
835 int subtractRelaxed(int value);
836
837 /// Atomically set the value of this object to the specified `swapValue`
838 /// and return its previous value.
839 int swap(int swapValue);
840
841 /// Atomically set the value of this object to the specified `swapValue`
842 /// and return its previous value, providing the acquire/release memory
843 /// ordering guarantee.
844 int swapAcqRel(int swapValue);
845
846 /// Compare the value of this object to the specified `compareValue`.
847 /// If they are equal, set the value of this atomic integer to the
848 /// specified `swapValue`, otherwise leave this value unchanged. Return
849 /// the previous value of this atomic integer, whether or not the swap
850 /// occurred. Note that the entire test-and-swap operation is performed
851 /// atomically.
852 int testAndSwap(int compareValue, int swapValue);
853
854 /// Compare the value of this object to the specified `compareValue`.
855 /// If they are equal, set the value of this atomic integer to the
856 /// specified `swapValue`, otherwise leave this value unchanged. Return
857 /// the previous value of this atomic integer, whether or not the swap
858 /// occurred. Note that the entire test-and-swap operation is performed
859 /// atomically and it provides the acquire/release memory ordering
860 /// guarantee.
861 int testAndSwapAcqRel(int compareValue, int swapValue);
862
863 // ACCESSORS
864
865 /// Return the current value of this object.
866 operator int() const;
867
868 /// Return the current value of this object.
869 int load() const;
870
871 /// Return the current value of this object, providing the acquire
872 /// memory ordering guarantee.
873 int loadAcquire() const;
874
875 /// Return the current value of this object, providing the relaxed
876 /// memory ordering guarantee.
877 int loadRelaxed() const;
878};
879
880 // =================
881 // class AtomicInt64
882 // =================
883
884/// This class is implements an atomic 64-bit integer, which supports common
885/// integer operations in a way that is guaranteed to be atomic. Operations
886/// on objects of this class provide the sequential consistency memory
887/// ordering guarantee unless explicitly qualified with a less strict
888/// consistency guarantee suffix (i.e., Acquire, Release, AcqRel or
889/// Relaxed).
890///
891/// See @ref bsls_atomic
893
894 // DATA
895 AtomicOperations::AtomicTypes::Int64 d_value;
896
897 private:
898 // NOT IMPLEMENTED
899
900 /// Note that the copy constructor and the copy-assignment operator are
901 /// not implemented because they cannot be done atomically.
902 AtomicInt64(const AtomicInt64&); // = delete
903 AtomicInt64& operator=(const AtomicInt64&); // = delete
904
905 public:
906 // CREATORS
907
908 /// Create an atomic 64-bit integer object having the default value 0.
909 AtomicInt64();
910
911 /// Create an atomic 64-bit integer object having the specified `value`.
913
914 ~AtomicInt64() = default;
915 // Destroy this atomic 64-bit integer object.
916
917 // MANIPULATORS
918
919 /// Atomically assign the specified `value` to this object, and return a
920 /// reference offering modifiable access to `this` object.
921 AtomicInt64& operator=(Types::Int64 value);
922
923 /// Atomically add the specified `value` to this object, and return the
924 /// resulting value.
926
927 /// Atomically subtract the specified `value` from this object, and
928 /// return the resulting value.
930
931 /// Atomically increment the value of this object by 1 and return the
932 /// resulting value.
934
935 /// Atomically increment the value of this object by 1 and return the
936 /// value prior to being incremented.
938
939 /// Atomically decrement the value of this object by 1 and return the
940 /// resulting value.
942
943 /// Atomically decrement the value of this object by 1 and return the
944 /// value prior to being decremented.
946
947 /// Atomically add the specified `value` to this object and return the
948 /// resulting value.
950
951 /// Atomically add the specified `value` to this object and return the
952 /// resulting value, providing the acquire/release memory ordering
953 /// guarantee.
955
956 /// Atomically add the specified `value` to this object and return the
957 /// resulting value, providing the relaxed memory ordering guarantee.
959
960 /// Atomically assign the specified `value` to this object, providing
961 /// the sequential consistency memory ordering guarantee.
962 void store(Types::Int64 value);
963
964 /// Atomically assign the specified `value` to this object, providing
965 /// the relaxed memory ordering guarantee.
966 void storeRelaxed(Types::Int64 value);
967
968 /// Atomically assign the specified `value` to this object, providing
969 /// the release memory ordering guarantee.
970 void storeRelease(Types::Int64 value);
971
972 /// Atomically subtract the specified `value` to this object and return
973 /// the resulting value.
975
976 /// Atomically subtract the specified `value` to this object and return
977 /// the resulting value, providing the acquire/release memory ordering
978 /// guarantee.
980
981 /// Atomically subtract the specified `value` to this object and return
982 /// the resulting value, providing the relaxed memory ordering
983 /// guarantee.
985
986 /// Atomically set the value of this object to the specified `swapValue`
987 /// and return its previous value.
988 Types::Int64 swap(Types::Int64 swapValue);
989
990 /// Atomically set the value of this object to the specified `swapValue`
991 /// and return its previous value, providing the acquire/release memory
992 /// ordering guarantee.
994
995 /// Compare the value of this object to the specified `compareValue`.
996 /// If they are equal, set the value of this atomic integer to the
997 /// specified `swapValue`, otherwise leave this value unchanged. Return
998 /// the previous value of this atomic integer, whether or not the swap
999 /// occurred. Note that the entire test-and-swap operation is performed
1000 /// atomically.
1002 Types::Int64 swapValue);
1003
1004 /// Compare the value of this object to the specified `compareValue`.
1005 /// If they are equal, set the value of this atomic integer to the
1006 /// specified `swapValue`, otherwise leave this value unchanged. Return
1007 /// the previous value of this atomic integer, whether or not the swap
1008 /// occurred. Note that the entire test-and-swap operation is performed
1009 /// atomically and it provides the acquire/release memory ordering
1010 /// guarantee.
1012 Types::Int64 swapValue);
1013
1014 // ACCESSORS
1015
1016 /// Return the current value of this object.
1017 operator Types::Int64() const;
1018
1019 /// Return the current value of this object.
1020 Types::Int64 load() const;
1021
1022 /// Return the current value of this object, providing the acquire
1023 /// memory ordering guarantee.
1024 Types::Int64 loadAcquire() const;
1025
1026 /// Return the current value of this object, providing the relaxed
1027 /// memory ordering guarantee.
1028 Types::Int64 loadRelaxed() const;
1029};
1030
1031 // ================
1032 // class AtomicUint
1033 // ================
1034
1035/// This class implements an atomic unsigned integer, which supports common
1036/// unsigned integer operations in a way that is guaranteed to be atomic.
1037/// Operations on objects of this class provide the sequential consistency
1038/// memory ordering guarantee unless explicitly qualified with a less strict
1039/// consistency guarantee suffix (i.e., Acquire, Release, AcqRel or
1040/// Relaxed).
1041///
1042/// See @ref bsls_atomic
1044
1045 // DATA
1046 AtomicOperations::AtomicTypes::Uint d_value;
1047
1048 private:
1049 // NOT IMPLEMENTED
1050
1051 /// Note that the copy constructor and the copy-assignment operator are
1052 /// not implemented because they cannot be done atomically.
1053 AtomicUint(const AtomicInt&); // = delete
1054 AtomicUint& operator=(const AtomicInt& ); // = delete
1055
1056 public:
1057 // CREATORS
1058
1059 /// Create an atomic unsigned integer object having the default value 0.
1060 AtomicUint();
1061
1062 /// Create an atomic unsigned integer object having the specified
1063 /// `value`.
1064 AtomicUint(unsigned int value);
1065
1066 ~AtomicUint() = default;
1067 // Destroy this atomic unsigned integer object.
1068
1069 // MANIPULATORS
1070
1071 /// Atomically assign the specified `value` to this object, and return a
1072 /// reference offering modifiable access to `this` object.
1073 AtomicUint& operator=(unsigned int value);
1074
1075 /// Atomically add the specified `value` to this object, and return the
1076 /// resulting value.
1077 unsigned int operator+=(unsigned int value);
1078
1079 /// Atomically subtract the specified `value` from this object, and
1080 /// return the resulting value.
1081 unsigned int operator-=(unsigned int value);
1082
1083 /// Atomically increment the value of this object by 1 and return the
1084 /// resulting value.
1085 unsigned int operator++();
1086
1087 /// Atomically increment the value of this object by 1 and return the
1088 /// value prior to being incremented.
1089 unsigned int operator++(int);
1090
1091 /// Atomically decrement the value of this object by 1 and return the
1092 /// resulting value.
1093 unsigned int operator--();
1094
1095 /// Atomically decrement the value of this object by 1 and return the
1096 /// value prior to being decremented.
1097 unsigned int operator--(int);
1098
1099 /// Atomically add the specified `value` to this object and return the
1100 /// resulting value.
1101 unsigned int add(unsigned int value);
1102
1103 /// Atomically add the specified `value` to this object and return the
1104 /// resulting value, providing the acquire/release memory ordering
1105 /// guarantee.
1106 unsigned int addAcqRel(unsigned int value);
1107
1108 /// Atomically add the specified `value` to this object and return the
1109 /// resulting value, providing the relaxed memory ordering guarantee.
1110 unsigned int addRelaxed(unsigned int value);
1111
1112 /// Atomically assign the specified `value` to this object, providing
1113 /// the sequential consistency memory ordering guarantee.
1114 void store(unsigned int value);
1115
1116 /// Atomically assign the specified `value` to this object, providing
1117 /// the relaxed memory ordering guarantee.
1118 void storeRelaxed(unsigned int value);
1119
1120 /// Atomically assign the specified `value` to this object, providing
1121 /// the release memory ordering guarantee.
1122 void storeRelease(unsigned int value);
1123
1124 /// Atomically subtract the specified `value` from this object and
1125 /// return the resulting value.
1126 unsigned int subtract(unsigned int value);
1127
1128 /// Atomically subtract the specified `value` from this object and
1129 /// return the resulting value, providing the acquire/release memory
1130 /// ordering guarantee.
1131 unsigned int subtractAcqRel(unsigned int value);
1132
1133 /// Atomically subtract the specified `value` from this object and
1134 /// return the resulting value, providing the relaxed memory ordering
1135 /// guarantee.
1136 unsigned int subtractRelaxed(unsigned int value);
1137
1138 /// Atomically set the value of this object to the specified `swapValue`
1139 /// and return its previous value.
1140 unsigned int swap(unsigned int swapValue);
1141
1142 /// Atomically set the value of this object to the specified `swapValue`
1143 /// and return its previous value, providing the acquire/release memory
1144 /// ordering guarantee.
1145 unsigned int swapAcqRel(unsigned int swapValue);
1146
1147 /// Compare the value of this object to the specified `compareValue`.
1148 /// If they are equal, set the value of this atomic unsigned integer to
1149 /// the specified `swapValue`, otherwise leave this value unchanged.
1150 /// Return the previous value of this atomic unsigned integer, whether
1151 /// or not the swap occurred. Note that the entire test-and-swap
1152 /// operation is performed atomically.
1153 unsigned int testAndSwap(unsigned int compareValue,
1154 unsigned int swapValue);
1155
1156 /// Compare the value of this object to the specified `compareValue`.
1157 /// If they are equal, set the value of this atomic unsigned integer to
1158 /// the specified `swapValue`, otherwise leave this value unchanged.
1159 /// Return the previous value of this atomic unsigned integer, whether
1160 /// or not the swap occurred. Note that the entire test-and-swap
1161 /// operation is performed atomically and it provides the
1162 /// acquire/release memory ordering guarantee.
1163 unsigned int testAndSwapAcqRel(unsigned int compareValue,
1164 unsigned int swapValue);
1165
1166 // ACCESSORS
1167
1168 /// Return the current value of this object.
1169 operator unsigned int() const;
1170
1171 /// Return the current value of this object.
1172 unsigned int load() const;
1173
1174 /// Return the current value of this object, providing the acquire
1175 /// memory ordering guarantee.
1176 unsigned int loadAcquire() const;
1177
1178 /// Return the current value of this object, providing the relaxed
1179 /// memory ordering guarantee.
1180 unsigned int loadRelaxed() const;
1181};
1182
1183 // ==================
1184 // class AtomicUint64
1185 // ==================
1186
1187/// This class is implements an atomic 64-bit unsigned integer, which
1188/// supports common unsigned integer operations in a way that is guaranteed
1189/// to be atomic. Operations on objects of this class provide the
1190/// sequential consistency memory ordering guarantee unless explicitly
1191/// qualified with a less strict consistency guarantee suffix (i.e.,
1192/// Acquire, Release, AcqRel or Relaxed).
1193///
1194/// See @ref bsls_atomic
1196
1197 // DATA
1198 AtomicOperations::AtomicTypes::Uint64 d_value;
1199
1200 private:
1201 // NOT IMPLEMENTED
1202
1203 /// Note that the copy constructor and the copy-assignment operator are
1204 /// not implemented because they cannot be done atomically.
1205 AtomicUint64(const AtomicUint64&); // = delete
1206 AtomicUint64& operator=(const AtomicUint64&); // = delete
1207
1208 public:
1209 // CREATORS
1210
1211 /// Create an atomic 64-bit unsigned integer object having the default
1212 /// value 0.
1213 AtomicUint64();
1214
1215 /// Create an atomic 64-bit unsigned integer object having the specified
1216 /// `value`.
1218
1219 ~AtomicUint64() = default;
1220 // Destroy this atomic 64-bit unsigned integer object.
1221
1222 // MANIPULATORS
1223
1224 /// Atomically assign the specified `value` to this object, and return a
1225 /// reference offering modifiable access to `this` object.
1226 AtomicUint64& operator=(Types::Uint64 value);
1227
1228 /// Atomically add the specified `value` to this object, and return the
1229 /// resulting value.
1231
1232 /// Atomically subtract the specified `value` from this object, and
1233 /// return the resulting value.
1235
1236 /// Atomically increment the value of this object by 1 and return the
1237 /// resulting value.
1239
1240 /// Atomically increment the value of this object by 1 and return the
1241 /// value prior to being incremented.
1243
1244 /// Atomically decrement the value of this object by 1 and return the
1245 /// resulting value.
1247
1248 /// Atomically decrement the value of this object by 1 and return the
1249 /// value prior to being decremented.
1251
1252 /// Atomically add the specified `value` to this object and return the
1253 /// resulting value.
1255
1256 /// Atomically add the specified `value` to this object and return the
1257 /// resulting value, providing the relaxed memory ordering guarantee.
1259
1260 /// Atomically add the specified `value` to this object and return the
1261 /// resulting value, providing the acquire/release memory ordering
1262 /// guarantee.
1264
1265 /// Atomically assign the specified `value` to this object, providing
1266 /// the sequential consistency memory ordering guarantee.
1267 void store(Types::Uint64 value);
1268
1269 /// Atomically assign the specified `value` to this object, providing
1270 /// the relaxed memory ordering guarantee.
1271 void storeRelaxed(Types::Uint64 value);
1272
1273 /// Atomically assign the specified `value` to this object, providing
1274 /// the release memory ordering guarantee.
1275 void storeRelease(Types::Uint64 value);
1276
1277 /// Atomically subtract the specified `value` from this object and
1278 /// return the resulting value.
1280
1281 /// Atomically subtract the specified `value` from this object and
1282 /// return the resulting value, providing the acquire/release memory
1283 /// ordering guarantee.
1285
1286 /// Atomically subtract the specified `value` from this object and
1287 /// return the resulting value, providing the relaxed memory ordering
1288 /// guarantee.
1290
1291 /// Atomically set the value of this object to the specified `swapValue`
1292 /// and return its previous value.
1293 Types::Uint64 swap(Types::Uint64 swapValue);
1294
1295 /// Atomically set the value of this object to the specified `swapValue`
1296 /// and return its previous value, providing the acquire/release memory
1297 /// ordering guarantee.
1299
1300 /// Compare the value of this object to the specified `compareValue`.
1301 /// If they are equal, set the value of this atomic 64-bit unsigned
1302 /// integer to the specified `swapValue`, otherwise leave this value
1303 /// unchanged. Return the previous value of this atomic unsigned
1304 /// integer, whether or not the swap occurred. Note that the entire
1305 /// test-and-swap operation is performed atomically.
1307 Types::Uint64 swapValue);
1308
1309 /// Compare the value of this object to the specified `compareValue`.
1310 /// If they are equal, set the value of this atomic 64-bit unsigned
1311 /// integer to the specified `swapValue`, otherwise leave this value
1312 /// unchanged. Return the previous value of this atomic unsigned
1313 /// integer, whether or not the swap occurred. Note that the entire
1314 /// test-and-swap operation is performed atomically and it provides the
1315 /// acquire/release memory ordering guarantee.
1317 Types::Uint64 swapValue);
1318
1319 // ACCESSORS
1320
1321 /// Return the current value of this object.
1322 operator Types::Uint64() const;
1323
1324 /// Return the current value of this object.
1325 Types::Uint64 load() const;
1326
1327 /// Return the current value of this object, providing the relaxed
1328 /// memory ordering guarantee.
1329 Types::Uint64 loadRelaxed() const;
1330
1331 /// Return the current value of this object, providing the acquire
1332 /// memory ordering guarantee.
1333 Types::Uint64 loadAcquire() const;
1334};
1335
1336 // ===================
1337 // class AtomicPointer
1338 // ===================
1339
1340/// This class implements an atomic pointer to a parameterized `TYPE`, which
1341/// supports common pointer operations in a way that is guaranteed to be
1342/// atomic. Operations on objects of this class provide the sequential
1343/// consistency memory ordering guarantee unless explicitly qualified with a
1344/// less strict consistency guarantee suffix (i.e., Acquire, Release, AcqRel
1345/// or Relaxed).
1346///
1347/// See @ref bsls_atomic
1348template <class TYPE>
1350
1351 // PRIVATE TYPES
1352
1353 /// Static assert that a `TYPE*` pointer is binary compatible with a
1354 /// `void*` pointer. The implementation of `AtomicPointer` uses
1355 /// @ref reinterpret_cast to convert between `TYPE*` and `void*` because
1356 /// function pointers are not implicitly convertible to `void*`, and
1357 /// this assert makes sure that such a cast is safe. Note that
1358 /// `bslmf_Assert` can't be used here because of package dependency
1359 /// rules.
1360 typedef char AtomicPointer_PointerSizeCheck[
1361 sizeof(TYPE *) == sizeof(void *) ? 1 : -1];
1362
1363 template <class TYPE1>
1364 struct RemoveConst { typedef TYPE1 Type; };
1365 template <class TYPE1>
1366 struct RemoveConst<TYPE1 const> { typedef TYPE1 Type; };
1367
1368 typedef typename RemoveConst<TYPE>::Type NcType;
1369
1370 // DATA
1371 AtomicOperations::AtomicTypes::Pointer d_value;
1372
1373 private:
1374 // NOT IMPLEMENTED
1375
1376 /// Note that the copy constructor and the copy-assignment operator are
1377 /// not implemented because they cannot be done atomically.
1378 AtomicPointer(const AtomicPointer<TYPE>&); // = delete
1379 AtomicPointer<TYPE>& operator=(const AtomicPointer<TYPE>&); // = delete
1380
1381 public:
1382 // CREATORS
1383
1384 /// Create an atomic pointer object having the default value NULL.
1386
1387 /// Create an atomic pointer object having the specified `value`.
1388 AtomicPointer(TYPE *value);
1389
1390 ~AtomicPointer() = default;
1391 // Destroy this atomic pointer.
1392
1393 // MANIPULATORS
1394
1395 /// Atomically assign the specified `value` to this object, and return a
1396 /// reference offering modifiable access to `this` object.
1398
1399 /// Atomically assign the specified `value` to this object, providing
1400 /// the sequential consistency memory ordering guarantee.
1401 void store(TYPE *value);
1402
1403 /// Atomically assign the specified `value` to this object, providing
1404 /// the relaxed memory ordering guarantee.
1405 void storeRelaxed(TYPE *value);
1406
1407 /// Atomically assign the specified `value` to this object, providing
1408 /// the release memory ordering guarantee.
1409 void storeRelease(TYPE *value);
1410
1411 /// Atomically set the value of this object to the specified `swapValue`
1412 /// and return its previous value.
1413 TYPE *swap(TYPE *swapValue);
1414
1415 /// Atomically set the value of this object to the specified `swapValue`
1416 /// and return its previous value, providing the acquire/release memory
1417 /// ordering guarantee.
1418 TYPE *swapAcqRel(TYPE *swapValue);
1419
1420 /// Compare the value of this object to the specified `compareValue`.
1421 /// If they are equal, set the value of this atomic pointer to the
1422 /// specified `swapValue`, otherwise leave this value unchanged. Return
1423 /// the previous value of this atomic pointer, whether or not the swap
1424 /// occurred. Note that the entire test-and-swap operation is performed
1425 /// atomically.
1426 TYPE *testAndSwap(const TYPE *compareValue, TYPE *swapValue);
1427
1428 /// Compare the value of this object to the specified `compareValue`.
1429 /// If they are equal, set the value of this atomic pointer to the
1430 /// specified `swapValue`, otherwise leave this value unchanged. Return
1431 /// the previous value of this atomic pointer, whether or not the swap
1432 /// occurred. Note that the entire test-and-swap operation is performed
1433 /// atomically and it provides the acquire/release memory ordering
1434 /// guarantee.
1435 TYPE *testAndSwapAcqRel(const TYPE *compareValue, TYPE *swapValue);
1436
1437 // ACCESSORS
1438
1439 /// Return a reference to the value currently pointed to by this object.
1440 /// The behavior is undefined if this pointer has a value of 0.
1441 TYPE& operator*() const;
1442
1443 /// Return the current value of this object.
1444 TYPE *operator->() const;
1445
1446 /// Return the current value of this object.
1447 operator TYPE*() const;
1448
1449 /// Return the current value of this object.
1450 TYPE *load() const;
1451
1452 /// Return the current value of this object, providing the relaxed
1453 /// memory ordering guarantee.
1454 TYPE *loadRelaxed() const;
1455
1456 /// Return the current value of this object, providing the acquire
1457 /// memory ordering guarantee.
1458 TYPE *loadAcquire() const;
1459};
1460
1461 // ================
1462 // class AtomicBool
1463 // ================
1464
1465/// This class implements an atomic boolean, which supports common boolean
1466/// operations in a way that is guaranteed to be atomic. Operations on
1467/// objects of this class provide the sequential consistency memory ordering
1468/// guarantee unless explicitly qualified with a less strict consistency
1469/// guarantee suffix (i.e., Acquire, Release, AcqRel or Relaxed).
1470///
1471/// See @ref bsls_atomic
1473
1474 // DATA
1475 enum {
1476 e_FALSE,
1477 e_TRUE
1478 };
1479 AtomicOperations::AtomicTypes::Int d_value;
1480
1481 private:
1482 // NOT IMPLEMENTED
1483
1484 /// Note that the copy constructor and the copy-assignment operator are
1485 /// not implemented because they cannot be done atomically.
1486 AtomicBool(const AtomicBool&); // = delete
1487 AtomicBool& operator=(const AtomicBool& ); // = delete
1488
1489 public:
1490 // CREATORS
1491
1492 /// Create an atomic boolean object having the default value `false`.
1493 AtomicBool();
1494
1495 /// Create an atomic boolean object having the specified `value`.
1496 AtomicBool(bool value);
1497
1498 ~AtomicBool() = default;
1499 // Destroy this atomic boolean object.
1500
1501 // MANIPULATORS
1502
1503 /// Atomically assign the specified `value` to this object, and return a
1504 /// reference offering modifiable access to `this` object.
1505 AtomicBool& operator=(bool value);
1506
1507 /// Atomically assign the specified `value` to this object, providing
1508 /// the sequential consistency memory ordering guarantee.
1509 void store(bool value);
1510
1511 /// Atomically assign the specified `value` to this object, providing
1512 /// the relaxed memory ordering guarantee.
1513 void storeRelaxed(bool value);
1514
1515 /// Atomically assign the specified `value` to this object, providing
1516 /// the release memory ordering guarantee.
1517 void storeRelease(bool value);
1518
1519 /// Atomically set the value of this object to the specified `swapValue`
1520 /// and return its previous value.
1521 bool swap(bool swapValue);
1522
1523 /// Atomically set the value of this object to the specified `swapValue`
1524 /// and return its previous value, providing the acquire/release memory
1525 /// ordering guarantee.
1526 bool swapAcqRel(bool swapValue);
1527
1528 /// Compare the value of this object to the specified `compareValue`.
1529 /// If they are equal, set the value of this atomic boolean to the
1530 /// specified `swapValue`, otherwise leave this value unchanged. Return
1531 /// the previous value of this atomic boolean, whether or not the swap
1532 /// occurred. Note that the entire test-and-swap operation is performed
1533 /// atomically.
1534 bool testAndSwap(bool compareValue, bool swapValue);
1535
1536 /// Compare the value of this object to the specified `compareValue`.
1537 /// If they are equal, set the value of this atomic boolean to the
1538 /// specified `swapValue`, otherwise leave this value unchanged. Return
1539 /// the previous value of this atomic boolean, whether or not the swap
1540 /// occurred. Note that the entire test-and-swap operation is performed
1541 /// atomically and it provides the acquire/release memory ordering
1542 /// guarantee.
1543 bool testAndSwapAcqRel(bool compareValue, bool swapValue);
1544
1545 // ACCESSORS
1546
1547 /// Return the current value of this object.
1548 operator bool() const;
1549
1550 /// Return the current value of this object.
1551 bool load() const;
1552
1553 /// Return the current value of this object, providing the relaxed
1554 /// memory ordering guarantee.
1555 bool loadRelaxed() const;
1556
1557 /// Return the current value of this object, providing the acquire
1558 /// memory ordering guarantee.
1559 bool loadAcquire() const;
1560};
1561
1562} // close package namespace
1563
1564namespace bsls {
1565
1566// ============================================================================
1567// INLINE FUNCTION DEFINITIONS
1568// ============================================================================
1569
1570 // ---------------
1571 // class AtomicInt
1572 // ---------------
1573
1574// CREATORS
1575inline
1577{
1578 AtomicOperations_Imp::initInt(&d_value, 0);
1579}
1580
1581inline
1583{
1584 AtomicOperations_Imp::initInt(&d_value, value);
1585}
1586
1587// MANIPULATORS
1588inline
1589AtomicInt& AtomicInt::operator=(int value)
1590{
1591 AtomicOperations_Imp::setInt(&d_value, value);
1592 return *this;
1593}
1594
1595inline
1597{
1598 return AtomicOperations_Imp::addIntNv(&d_value, value);
1599}
1600
1601inline
1603{
1604 return AtomicOperations_Imp::subtractIntNv(&d_value, value);
1605}
1606
1607inline
1609{
1610 return AtomicOperations_Imp::incrementIntNv(&d_value);
1611}
1612
1613inline
1615{
1616 return static_cast<int>(
1617 static_cast<unsigned int>(
1618 AtomicOperations_Imp::incrementIntNv(&d_value)) - 1);
1619}
1620
1621inline
1623{
1624 return AtomicOperations_Imp::decrementIntNv(&d_value);
1625}
1626
1627inline
1629{
1630 return static_cast<int>(
1631 static_cast<unsigned int>(
1632 AtomicOperations_Imp::decrementIntNv(&d_value)) + 1);
1633}
1634
1635inline
1636int AtomicInt::add(int value)
1637{
1638 return AtomicOperations_Imp::addIntNv(&d_value, value);
1639}
1640
1641inline
1643{
1644 return AtomicOperations_Imp::addIntNvAcqRel(&d_value, value);
1645}
1646
1647inline
1649{
1650 return AtomicOperations_Imp::addIntNvRelaxed(&d_value, value);
1651}
1652
1653inline
1654void AtomicInt::store(int value)
1655{
1656 AtomicOperations_Imp::setInt(&d_value, value);
1657}
1658
1659inline
1661{
1662 AtomicOperations_Imp::setIntRelaxed(&d_value, value);
1663}
1664
1665inline
1667{
1668 AtomicOperations_Imp::setIntRelease(&d_value, value);
1669}
1670
1671inline
1673{
1674 return AtomicOperations_Imp::subtractIntNv(&d_value, value);
1675}
1676
1677inline
1679{
1680 return AtomicOperations_Imp::subtractIntNvAcqRel(&d_value, value);
1681}
1682
1683inline
1685{
1686 return AtomicOperations_Imp::subtractIntNvRelaxed(&d_value, value);
1687}
1688
1689inline
1690int AtomicInt::swap(int swapValue)
1691{
1692 return AtomicOperations_Imp::swapInt(&d_value, swapValue);
1693}
1694
1695inline
1696int AtomicInt::swapAcqRel(int swapValue)
1697{
1698 return AtomicOperations_Imp::swapIntAcqRel(&d_value, swapValue);
1699}
1700
1701inline
1702int AtomicInt::testAndSwap(int compareValue, int swapValue)
1703{
1704 return AtomicOperations_Imp::testAndSwapInt(&d_value,
1705 compareValue,
1706 swapValue);
1707}
1708
1709inline
1710int AtomicInt::testAndSwapAcqRel(int compareValue, int swapValue)
1711{
1712 return AtomicOperations_Imp::testAndSwapIntAcqRel(&d_value,
1713 compareValue,
1714 swapValue);
1715}
1716
1717// ACCESSORS
1718
1719inline
1720AtomicInt::operator int() const
1721{
1722 return AtomicOperations_Imp::getInt(&d_value);
1723}
1724
1725inline
1727{
1728 return this->operator int();
1729}
1730
1731inline
1733{
1734 return AtomicOperations_Imp::getIntAcquire(&d_value);
1735}
1736
1737inline
1739{
1740 return AtomicOperations_Imp::getIntRelaxed(&d_value);
1741}
1742
1743 // -----------------
1744 // class AtomicInt64
1745 // -----------------
1746
1747// CREATORS
1748inline
1750{
1751 AtomicOperations_Imp::initInt64(&d_value, 0);
1752}
1753
1754inline
1756{
1757 AtomicOperations_Imp::initInt64(&d_value, value);
1758}
1759
1760// MANIPULATORS
1761inline
1762AtomicInt64& AtomicInt64::operator=(Types::Int64 value)
1763{
1764 AtomicOperations_Imp::setInt64(&d_value, value);
1765 return *this;
1766}
1767
1768inline
1770{
1771 return AtomicOperations_Imp::addInt64Nv(&d_value, value);
1772}
1773
1774inline
1776{
1777 return AtomicOperations_Imp::subtractInt64Nv(&d_value, value);
1778}
1779
1780inline
1782{
1783 return AtomicOperations_Imp::incrementInt64Nv(&d_value);
1784}
1785
1786inline
1788{
1789 return static_cast<Types::Int64>(
1790 static_cast<Types::Uint64>(
1791 AtomicOperations_Imp::incrementInt64Nv(&d_value)) - 1);
1792}
1793
1794inline
1796{
1797 return AtomicOperations_Imp::decrementInt64Nv(&d_value);
1798}
1799
1800inline
1802{
1803 return static_cast<Types::Int64>(
1804 static_cast<Types::Uint64>(
1805 AtomicOperations_Imp::decrementInt64Nv(&d_value)) + 1);
1806}
1807
1808inline
1810{
1811 return AtomicOperations_Imp::addInt64Nv(&d_value, value);
1812}
1813
1814inline
1816{
1817 return AtomicOperations_Imp::addInt64NvAcqRel(&d_value, value);
1818}
1819
1820inline
1822{
1823 return AtomicOperations_Imp::addInt64NvRelaxed(&d_value, value);
1824}
1825
1826inline
1828{
1829 AtomicOperations_Imp::setInt64(&d_value, value);
1830}
1831
1832inline
1834{
1835 AtomicOperations_Imp::setInt64Relaxed(&d_value, value);
1836}
1837
1838inline
1840{
1841 AtomicOperations_Imp::setInt64Release(&d_value, value);
1842}
1843
1844inline
1846{
1847 return AtomicOperations_Imp::subtractInt64Nv(&d_value, value);
1848}
1849
1850inline
1852{
1853 return AtomicOperations_Imp::subtractInt64NvAcqRel(&d_value, value);
1854}
1855
1856inline
1858{
1859 return AtomicOperations_Imp::subtractInt64NvRelaxed(&d_value, value);
1860}
1861
1862inline
1864{
1865 return AtomicOperations_Imp::swapInt64(&d_value, swapValue);
1866}
1867
1868inline
1870{
1871 return AtomicOperations_Imp::swapInt64AcqRel(&d_value, swapValue);
1872}
1873
1874inline
1877 Types::Int64 swapValue)
1878{
1879 return AtomicOperations_Imp::testAndSwapInt64(&d_value,
1880 compareValue,
1881 swapValue);
1882}
1883
1884inline
1887 Types::Int64 swapValue)
1888{
1889 return AtomicOperations_Imp::testAndSwapInt64AcqRel(&d_value,
1890 compareValue,
1891 swapValue);
1892}
1893
1894// ACCESSORS
1895inline
1896AtomicInt64::operator Types::Int64() const
1897{
1898 return AtomicOperations_Imp::getInt64(&d_value);
1899}
1900
1901inline
1903{
1904 return this->operator Types::Int64();
1905}
1906
1907inline
1909{
1910 return AtomicOperations_Imp::getInt64Acquire(&d_value);
1911}
1912
1913inline
1915{
1916 return AtomicOperations_Imp::getInt64Relaxed(&d_value);
1917}
1918
1919 // ---------------
1920 // class AtomicUint
1921 // ---------------
1922
1923// CREATORS
1924inline
1926{
1927 AtomicOperations_Imp::initUint(&d_value, 0);
1928}
1929
1930inline
1931AtomicUint::AtomicUint(unsigned int value)
1932{
1933 AtomicOperations_Imp::initUint(&d_value, value);
1934}
1935
1936// MANIPULATORS
1937inline
1938AtomicUint& AtomicUint::operator=(unsigned int value)
1939{
1940 AtomicOperations_Imp::setUint(&d_value, value);
1941 return *this;
1942}
1943
1944inline
1945unsigned int AtomicUint::operator+=(unsigned int value)
1946{
1947 return AtomicOperations_Imp::addUintNv(&d_value, value);
1948}
1949
1950inline
1951unsigned int AtomicUint::operator-=(unsigned int value)
1952{
1953 return AtomicOperations_Imp::subtractUintNv(&d_value, value);
1954}
1955
1956inline
1958{
1959 return AtomicOperations_Imp::incrementUintNv(&d_value);
1960}
1961
1962inline
1963unsigned int AtomicUint::operator++(int)
1964{
1965 return AtomicOperations_Imp::incrementUintNv(&d_value) - 1;
1966}
1967
1968inline
1970{
1971 return AtomicOperations_Imp::decrementUintNv(&d_value);
1972}
1973
1974inline
1975unsigned int AtomicUint::operator--(int)
1976{
1977 return AtomicOperations_Imp::decrementUintNv(&d_value) + 1;
1978}
1979
1980inline
1981unsigned int AtomicUint::add(unsigned int value)
1982{
1983 return AtomicOperations_Imp::addUintNv(&d_value, value);
1984}
1985
1986inline
1987unsigned int AtomicUint::addAcqRel(unsigned int value)
1988{
1989 return AtomicOperations_Imp::addUintNvAcqRel(&d_value, value);
1990}
1991
1992inline
1993unsigned int AtomicUint::addRelaxed(unsigned int value)
1994{
1995 return AtomicOperations_Imp::addUintNvRelaxed(&d_value, value);
1996}
1997
1998inline
1999void AtomicUint::store(unsigned int value)
2000{
2001 AtomicOperations_Imp::setUint(&d_value, value);
2002}
2003
2004inline
2005void AtomicUint::storeRelaxed(unsigned int value)
2006{
2007 AtomicOperations_Imp::setUintRelaxed(&d_value, value);
2008}
2009
2010inline
2011void AtomicUint::storeRelease(unsigned int value)
2012{
2013 AtomicOperations_Imp::setUintRelease(&d_value, value);
2014}
2015
2016inline
2017unsigned int AtomicUint::subtract(unsigned int value)
2018{
2019 return AtomicOperations_Imp::subtractUintNv(&d_value, value);
2020}
2021
2022inline
2023unsigned int AtomicUint::subtractAcqRel(unsigned int value)
2024{
2025 return AtomicOperations_Imp::subtractUintNvAcqRel(&d_value, value);
2026}
2027
2028inline
2029unsigned int AtomicUint::subtractRelaxed(unsigned int value)
2030{
2031 return AtomicOperations_Imp::subtractUintNvRelaxed(&d_value, value);
2032}
2033
2034inline
2035unsigned int AtomicUint::swap(unsigned int swapValue)
2036{
2037 return AtomicOperations_Imp::swapUint(&d_value, swapValue);
2038}
2039
2040inline
2041unsigned int AtomicUint::swapAcqRel(unsigned int swapValue)
2042{
2043 return AtomicOperations_Imp::swapUintAcqRel(&d_value, swapValue);
2044}
2045
2046inline
2047unsigned int AtomicUint::testAndSwap(unsigned int compareValue,
2048 unsigned int swapValue)
2049{
2050 return AtomicOperations_Imp::testAndSwapUint(&d_value,
2051 compareValue,
2052 swapValue);
2053}
2054
2055inline
2056unsigned int AtomicUint::testAndSwapAcqRel(unsigned int compareValue,
2057 unsigned int swapValue)
2058{
2059 return AtomicOperations_Imp::testAndSwapUintAcqRel(&d_value,
2060 compareValue,
2061 swapValue);
2062}
2063
2064// ACCESSORS
2065
2066inline
2067AtomicUint::operator unsigned int() const
2068{
2069 return AtomicOperations_Imp::getUint(&d_value);
2070}
2071
2072inline
2073unsigned int AtomicUint::load() const
2074{
2075 return this->operator unsigned int();
2076}
2077
2078inline
2079unsigned int AtomicUint::loadAcquire() const
2080{
2081 return AtomicOperations_Imp::getUintAcquire(&d_value);
2082}
2083
2084inline
2085unsigned int AtomicUint::loadRelaxed() const
2086{
2087 return AtomicOperations_Imp::getUintRelaxed(&d_value);
2088}
2089
2090 // -----------------
2091 // class AtomicUint64
2092 // -----------------
2093
2094// CREATORS
2095inline
2097{
2098 AtomicOperations_Imp::initUint64(&d_value, 0);
2099}
2100
2101inline
2103{
2104 AtomicOperations_Imp::initUint64(&d_value, value);
2105}
2106
2107// MANIPULATORS
2108inline
2109AtomicUint64& AtomicUint64::operator=(Types::Uint64 value)
2110{
2111 AtomicOperations_Imp::setUint64(&d_value, value);
2112 return *this;
2113}
2114
2115inline
2117{
2118 return AtomicOperations_Imp::addUint64Nv(&d_value, value);
2119}
2120
2121inline
2123{
2124 return AtomicOperations_Imp::subtractUint64Nv(&d_value, value);
2125}
2126
2127inline
2129{
2130 return AtomicOperations_Imp::incrementUint64Nv(&d_value);
2131}
2132
2133inline
2135{
2136 return AtomicOperations_Imp::incrementUint64Nv(&d_value) - 1;
2137}
2138
2139inline
2141{
2142 return AtomicOperations_Imp::decrementUint64Nv(&d_value);
2143}
2144
2145inline
2147{
2148 return AtomicOperations_Imp::decrementUint64Nv(&d_value) + 1;
2149}
2150
2151inline
2153{
2154 return AtomicOperations_Imp::addUint64Nv(&d_value, value);
2155}
2156
2157inline
2159{
2160 return AtomicOperations_Imp::addUint64NvAcqRel(&d_value, value);
2161}
2162
2163inline
2165{
2166 return AtomicOperations_Imp::addUint64NvRelaxed(&d_value, value);
2167}
2168
2169inline
2171{
2172 AtomicOperations_Imp::setUint64(&d_value, value);
2173}
2174
2175inline
2177{
2178 AtomicOperations_Imp::setUint64Relaxed(&d_value, value);
2179}
2180
2181inline
2183{
2184 AtomicOperations_Imp::setUint64Release(&d_value, value);
2185}
2186
2187inline
2189{
2190 return AtomicOperations_Imp::subtractUint64Nv(&d_value, value);
2191}
2192
2193inline
2195{
2196 return AtomicOperations_Imp::subtractUint64NvAcqRel(&d_value, value);
2197}
2198
2199inline
2201{
2202 return AtomicOperations_Imp::subtractUint64NvRelaxed(&d_value, value);
2203}
2204
2205inline
2207{
2208 return AtomicOperations_Imp::swapUint64(&d_value, swapValue);
2209}
2210
2211inline
2213{
2214 return AtomicOperations_Imp::swapUint64AcqRel(&d_value, swapValue);
2215}
2216
2217inline
2219 Types::Uint64 swapValue)
2220{
2221 return AtomicOperations_Imp::testAndSwapUint64(&d_value,
2222 compareValue,
2223 swapValue);
2224}
2225
2226inline
2228 Types::Uint64 swapValue)
2229{
2230 return AtomicOperations_Imp::testAndSwapUint64AcqRel(&d_value,
2231 compareValue,
2232 swapValue);
2233}
2234
2235// ACCESSORS
2236inline
2237AtomicUint64::operator Types::Uint64() const
2238{
2239 return AtomicOperations_Imp::getUint64(&d_value);
2240}
2241
2242inline
2244{
2245 return this->operator Types::Uint64();
2246}
2247
2248inline
2250{
2251 return AtomicOperations_Imp::getUint64Acquire(&d_value);
2252}
2253
2254inline
2256{
2257 return AtomicOperations_Imp::getUint64Relaxed(&d_value);
2258}
2259
2260 // -------------------
2261 // class AtomicPointer
2262 // -------------------
2263
2264// CREATORS
2265template <class TYPE>
2266inline
2268{
2269 AtomicOperations_Imp::initPointer(&d_value, 0);
2270}
2271
2272template <class TYPE>
2273inline
2275{
2276 AtomicOperations_Imp::initPointer(
2277 &d_value,
2278 reinterpret_cast<void *>(const_cast<NcType *>(value)));
2279}
2280
2281// MANIPULATORS
2282template <class TYPE>
2283inline
2286{
2287 AtomicOperations_Imp::setPtr(
2288 &d_value,
2289 reinterpret_cast<void *>(const_cast<NcType *>(value)));
2290 return *this;
2291}
2292
2293template <class TYPE>
2294inline
2296{
2297 AtomicOperations_Imp::setPtr(
2298 &d_value,
2299 reinterpret_cast<void *>(const_cast<NcType *>(value)));
2300}
2301
2302template <class TYPE>
2303inline
2305{
2306 AtomicOperations_Imp::setPtrRelaxed(
2307 &d_value,
2308 reinterpret_cast<void *>(const_cast<NcType *>(value)));
2309}
2310
2311template <class TYPE>
2312inline
2314{
2315 AtomicOperations_Imp::setPtrRelease(
2316 &d_value,
2317 reinterpret_cast<void *>(const_cast<NcType *>(value)));
2318}
2319
2320template <class TYPE>
2321inline
2322TYPE *AtomicPointer<TYPE>::swap(TYPE *swapValue)
2323{
2324 return reinterpret_cast<TYPE *>(
2325 AtomicOperations_Imp::swapPtr(
2326 &d_value,
2327 reinterpret_cast<void *>(const_cast<NcType *>(swapValue))));
2328}
2329
2330template <class TYPE>
2331inline
2333{
2334 return reinterpret_cast<TYPE *>(
2335 AtomicOperations_Imp::swapPtrAcqRel(
2336 &d_value,
2337 reinterpret_cast<void *>(const_cast<NcType *>(swapValue))));
2338}
2339
2340template <class TYPE>
2341inline
2342TYPE *AtomicPointer<TYPE>::testAndSwap(const TYPE *compareValue,
2343 TYPE *swapValue)
2344{
2345 return reinterpret_cast<TYPE *>(
2346 AtomicOperations_Imp::testAndSwapPtr(
2347 &d_value,
2348 reinterpret_cast<void *>(const_cast<NcType *>(compareValue)),
2349 reinterpret_cast<void *>(const_cast<NcType *>(swapValue))));
2350}
2351
2352template <class TYPE>
2353inline
2354TYPE *AtomicPointer<TYPE>::testAndSwapAcqRel(const TYPE *compareValue,
2355 TYPE *swapValue)
2356{
2357 return reinterpret_cast<TYPE *>(
2358 AtomicOperations_Imp::testAndSwapPtrAcqRel(
2359 &d_value,
2360 reinterpret_cast<void *>(const_cast<NcType *>(compareValue)),
2361 reinterpret_cast<void *>(const_cast<NcType *>(swapValue))));
2362}
2363
2364// ACCESSORS
2365template <class TYPE>
2366inline
2368{
2369 return static_cast<TYPE *>(AtomicOperations_Imp::getPtr(&d_value));
2370}
2371
2372template <class TYPE>
2373inline
2375{
2376 return *(static_cast<TYPE *>(AtomicOperations_Imp::getPtr(&d_value)));
2377}
2378
2379template <class TYPE>
2380inline
2382{
2383 return static_cast<TYPE *>(AtomicOperations_Imp::getPtr(&d_value));
2384}
2385
2386template <class TYPE>
2387inline
2389{
2390 return this->operator TYPE*();
2391}
2392
2393template <class TYPE>
2394inline
2396{
2397 return static_cast<TYPE *>(AtomicOperations_Imp::getPtrAcquire(&d_value));
2398}
2399
2400template <class TYPE>
2401inline
2403{
2404 return static_cast<TYPE *>(AtomicOperations_Imp::getPtrRelaxed(&d_value));
2405}
2406
2407 // ----------------
2408 // class AtomicBool
2409 // ----------------
2410
2411// CREATORS
2412inline
2414{
2415 AtomicOperations_Imp::initInt(&d_value, AtomicBool::e_FALSE);
2416}
2417
2418inline
2420{
2421 AtomicOperations_Imp::initInt(
2422 &d_value,
2423 value ? AtomicBool::e_TRUE : AtomicBool::e_FALSE);
2424}
2425
2426// MANIPULATORS
2427inline
2428AtomicBool& AtomicBool::operator=(bool value)
2429{
2430 AtomicOperations_Imp::setInt(
2431 &d_value,
2432 value ? AtomicBool::e_TRUE : AtomicBool::e_FALSE);
2433 return *this;
2434}
2435
2436inline
2437void AtomicBool::store(bool value)
2438{
2439 AtomicOperations_Imp::setInt(
2440 &d_value,
2441 value ? AtomicBool::e_TRUE : AtomicBool::e_FALSE);
2442}
2443
2444inline
2446{
2447 AtomicOperations_Imp::setIntRelaxed(
2448 &d_value,
2449 value ? AtomicBool::e_TRUE : AtomicBool::e_FALSE);
2450}
2451
2452inline
2454{
2455 AtomicOperations_Imp::setIntRelease(
2456 &d_value,
2457 value ? AtomicBool::e_TRUE : AtomicBool::e_FALSE);
2458}
2459
2460inline
2461bool AtomicBool::swap(bool swapValue)
2462{
2463 return AtomicOperations_Imp::swapInt(
2464 &d_value,
2465 swapValue ? AtomicBool::e_TRUE : AtomicBool::e_FALSE)
2466 == AtomicBool::e_TRUE;
2467}
2468
2469inline
2470bool AtomicBool::swapAcqRel(bool swapValue)
2471{
2472 return AtomicOperations_Imp::swapIntAcqRel(
2473 &d_value,
2474 swapValue ? AtomicBool::e_TRUE : AtomicBool::e_FALSE)
2475 == AtomicBool::e_TRUE;
2476}
2477
2478inline
2479bool AtomicBool::testAndSwap(bool compareValue, bool swapValue)
2480{
2481 return AtomicOperations_Imp::testAndSwapInt(
2482 &d_value,
2483 compareValue ? AtomicBool::e_TRUE : AtomicBool::e_FALSE,
2484 swapValue ? AtomicBool::e_TRUE : AtomicBool::e_FALSE)
2485 == AtomicBool::e_TRUE;
2486}
2487
2488inline
2489bool AtomicBool::testAndSwapAcqRel(bool compareValue, bool swapValue)
2490{
2491 return AtomicOperations_Imp::testAndSwapIntAcqRel(
2492 &d_value,
2493 compareValue ? AtomicBool::e_TRUE : AtomicBool::e_FALSE,
2494 swapValue ? AtomicBool::e_TRUE : AtomicBool::e_FALSE)
2495 == AtomicBool::e_TRUE;
2496}
2497
2498// ACCESSORS
2499
2500inline
2501AtomicBool::operator bool() const
2502{
2503 return AtomicOperations_Imp::getInt(&d_value) == AtomicBool::e_TRUE;
2504}
2505
2506inline
2508{
2509 return this->operator bool();
2510}
2511
2512inline
2514{
2515 return AtomicOperations_Imp::getIntAcquire(&d_value) == AtomicBool::e_TRUE;
2516}
2517
2518inline
2520{
2521 return AtomicOperations_Imp::getIntRelaxed(&d_value) == AtomicBool::e_TRUE;
2522}
2523
2524} // close package namespace
2525
2526
2527
2528#endif
2529
2530// ----------------------------------------------------------------------------
2531// Copyright 2013 Bloomberg Finance L.P.
2532//
2533// Licensed under the Apache License, Version 2.0 (the "License");
2534// you may not use this file except in compliance with the License.
2535// You may obtain a copy of the License at
2536//
2537// http://www.apache.org/licenses/LICENSE-2.0
2538//
2539// Unless required by applicable law or agreed to in writing, software
2540// distributed under the License is distributed on an "AS IS" BASIS,
2541// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2542// See the License for the specific language governing permissions and
2543// limitations under the License.
2544// ----------------------------- END-OF-FILE ----------------------------------
2545
2546/** @} */
2547/** @} */
2548/** @} */
Definition bsls_atomic.h:1472
void storeRelease(bool value)
Definition bsls_atomic.h:2453
bool swap(bool swapValue)
Definition bsls_atomic.h:2461
~AtomicBool()=default
void store(bool value)
Definition bsls_atomic.h:2437
AtomicBool()
Create an atomic boolean object having the default value false.
Definition bsls_atomic.h:2413
bool testAndSwap(bool compareValue, bool swapValue)
Definition bsls_atomic.h:2479
bool loadRelaxed() const
Definition bsls_atomic.h:2519
bool load() const
Return the current value of this object.
Definition bsls_atomic.h:2507
bool swapAcqRel(bool swapValue)
Definition bsls_atomic.h:2470
bool testAndSwapAcqRel(bool compareValue, bool swapValue)
Definition bsls_atomic.h:2489
void storeRelaxed(bool value)
Definition bsls_atomic.h:2445
bool loadAcquire() const
Definition bsls_atomic.h:2513
Definition bsls_atomic.h:892
Types::Int64 swap(Types::Int64 swapValue)
Definition bsls_atomic.h:1863
Types::Int64 operator-=(Types::Int64 value)
Definition bsls_atomic.h:1775
Types::Int64 operator++()
Definition bsls_atomic.h:1781
Types::Int64 loadRelaxed() const
Definition bsls_atomic.h:1914
Types::Int64 subtract(Types::Int64 value)
Definition bsls_atomic.h:1845
Types::Int64 add(Types::Int64 value)
Definition bsls_atomic.h:1809
Types::Int64 operator--()
Definition bsls_atomic.h:1795
Types::Int64 load() const
Return the current value of this object.
Definition bsls_atomic.h:1902
AtomicInt64()
Create an atomic 64-bit integer object having the default value 0.
Definition bsls_atomic.h:1749
Types::Int64 operator+=(Types::Int64 value)
Definition bsls_atomic.h:1769
Types::Int64 addRelaxed(Types::Int64 value)
Definition bsls_atomic.h:1821
Types::Int64 subtractAcqRel(Types::Int64 value)
Definition bsls_atomic.h:1851
Types::Int64 testAndSwapAcqRel(Types::Int64 compareValue, Types::Int64 swapValue)
Definition bsls_atomic.h:1886
void storeRelaxed(Types::Int64 value)
Definition bsls_atomic.h:1833
~AtomicInt64()=default
Types::Int64 addAcqRel(Types::Int64 value)
Definition bsls_atomic.h:1815
Types::Int64 subtractRelaxed(Types::Int64 value)
Definition bsls_atomic.h:1857
Types::Int64 loadAcquire() const
Definition bsls_atomic.h:1908
Types::Int64 testAndSwap(Types::Int64 compareValue, Types::Int64 swapValue)
Definition bsls_atomic.h:1876
void store(Types::Int64 value)
Definition bsls_atomic.h:1827
Types::Int64 swapAcqRel(Types::Int64 swapValue)
Definition bsls_atomic.h:1869
void storeRelease(Types::Int64 value)
Definition bsls_atomic.h:1839
Definition bsls_atomic.h:743
int subtractAcqRel(int value)
Definition bsls_atomic.h:1678
int operator--()
Definition bsls_atomic.h:1622
int loadAcquire() const
Definition bsls_atomic.h:1732
void storeRelease(int value)
Definition bsls_atomic.h:1666
int swapAcqRel(int swapValue)
Definition bsls_atomic.h:1696
int operator-=(int value)
Definition bsls_atomic.h:1602
AtomicInt()
Create an atomic integer object having the default value 0.
Definition bsls_atomic.h:1576
int addRelaxed(int value)
Definition bsls_atomic.h:1648
void store(int value)
Definition bsls_atomic.h:1654
int operator+=(int value)
Definition bsls_atomic.h:1596
int swap(int swapValue)
Definition bsls_atomic.h:1690
int loadRelaxed() const
Definition bsls_atomic.h:1738
int addAcqRel(int value)
Definition bsls_atomic.h:1642
int subtract(int value)
Definition bsls_atomic.h:1672
~AtomicInt()=default
int testAndSwapAcqRel(int compareValue, int swapValue)
Definition bsls_atomic.h:1710
void storeRelaxed(int value)
Definition bsls_atomic.h:1660
int subtractRelaxed(int value)
Definition bsls_atomic.h:1684
int load() const
Return the current value of this object.
Definition bsls_atomic.h:1726
int operator++()
Definition bsls_atomic.h:1608
int add(int value)
Definition bsls_atomic.h:1636
int testAndSwap(int compareValue, int swapValue)
Definition bsls_atomic.h:1702
Definition bsls_atomic.h:1349
~AtomicPointer()=default
void store(TYPE *value)
Definition bsls_atomic.h:2295
void storeRelaxed(TYPE *value)
Definition bsls_atomic.h:2304
AtomicPointer(TYPE *value)
Create an atomic pointer object having the specified value.
Definition bsls_atomic.h:2274
void storeRelease(TYPE *value)
Definition bsls_atomic.h:2313
TYPE * swap(TYPE *swapValue)
Definition bsls_atomic.h:2322
TYPE & operator*() const
Definition bsls_atomic.h:2374
TYPE * swapAcqRel(TYPE *swapValue)
Definition bsls_atomic.h:2332
TYPE * operator->() const
Return the current value of this object.
Definition bsls_atomic.h:2381
AtomicPointer()
Create an atomic pointer object having the default value NULL.
Definition bsls_atomic.h:2267
TYPE * loadRelaxed() const
Definition bsls_atomic.h:2402
TYPE * loadAcquire() const
Definition bsls_atomic.h:2395
TYPE * load() const
Return the current value of this object.
Definition bsls_atomic.h:2388
TYPE * testAndSwapAcqRel(const TYPE *compareValue, TYPE *swapValue)
Definition bsls_atomic.h:2354
AtomicPointer< TYPE > & operator=(TYPE *value)
Definition bsls_atomic.h:2285
TYPE * testAndSwap(const TYPE *compareValue, TYPE *swapValue)
Definition bsls_atomic.h:2342
Definition bsls_atomic.h:1195
AtomicUint64()
Definition bsls_atomic.h:2096
Types::Uint64 addRelaxed(Types::Uint64 value)
Definition bsls_atomic.h:2164
Types::Uint64 testAndSwapAcqRel(Types::Uint64 compareValue, Types::Uint64 swapValue)
Definition bsls_atomic.h:2227
Types::Uint64 operator+=(Types::Uint64 value)
Definition bsls_atomic.h:2116
Types::Uint64 loadRelaxed() const
Definition bsls_atomic.h:2255
Types::Uint64 subtractAcqRel(Types::Uint64 value)
Definition bsls_atomic.h:2194
Types::Uint64 swap(Types::Uint64 swapValue)
Definition bsls_atomic.h:2206
Types::Uint64 testAndSwap(Types::Uint64 compareValue, Types::Uint64 swapValue)
Definition bsls_atomic.h:2218
Types::Uint64 subtract(Types::Uint64 value)
Definition bsls_atomic.h:2188
Types::Uint64 loadAcquire() const
Definition bsls_atomic.h:2249
Types::Uint64 swapAcqRel(Types::Uint64 swapValue)
Definition bsls_atomic.h:2212
Types::Uint64 subtractRelaxed(Types::Uint64 value)
Definition bsls_atomic.h:2200
~AtomicUint64()=default
Types::Uint64 operator--()
Definition bsls_atomic.h:2140
void storeRelease(Types::Uint64 value)
Definition bsls_atomic.h:2182
Types::Uint64 addAcqRel(Types::Uint64 value)
Definition bsls_atomic.h:2158
void store(Types::Uint64 value)
Definition bsls_atomic.h:2170
Types::Uint64 operator-=(Types::Uint64 value)
Definition bsls_atomic.h:2122
Types::Uint64 add(Types::Uint64 value)
Definition bsls_atomic.h:2152
Types::Uint64 operator++()
Definition bsls_atomic.h:2128
Types::Uint64 load() const
Return the current value of this object.
Definition bsls_atomic.h:2243
void storeRelaxed(Types::Uint64 value)
Definition bsls_atomic.h:2176
Definition bsls_atomic.h:1043
unsigned int swap(unsigned int swapValue)
Definition bsls_atomic.h:2035
unsigned int load() const
Return the current value of this object.
Definition bsls_atomic.h:2073
AtomicUint()
Create an atomic unsigned integer object having the default value 0.
Definition bsls_atomic.h:1925
unsigned int addRelaxed(unsigned int value)
Definition bsls_atomic.h:1993
unsigned int testAndSwapAcqRel(unsigned int compareValue, unsigned int swapValue)
Definition bsls_atomic.h:2056
unsigned int loadAcquire() const
Definition bsls_atomic.h:2079
void storeRelaxed(unsigned int value)
Definition bsls_atomic.h:2005
unsigned int add(unsigned int value)
Definition bsls_atomic.h:1981
unsigned int operator--()
Definition bsls_atomic.h:1969
unsigned int subtractAcqRel(unsigned int value)
Definition bsls_atomic.h:2023
unsigned int testAndSwap(unsigned int compareValue, unsigned int swapValue)
Definition bsls_atomic.h:2047
void store(unsigned int value)
Definition bsls_atomic.h:1999
unsigned int subtract(unsigned int value)
Definition bsls_atomic.h:2017
unsigned int swapAcqRel(unsigned int swapValue)
Definition bsls_atomic.h:2041
unsigned int subtractRelaxed(unsigned int value)
Definition bsls_atomic.h:2029
unsigned int addAcqRel(unsigned int value)
Definition bsls_atomic.h:1987
unsigned int operator-=(unsigned int value)
Definition bsls_atomic.h:1951
unsigned int loadRelaxed() const
Definition bsls_atomic.h:2085
void storeRelease(unsigned int value)
Definition bsls_atomic.h:2011
unsigned int operator+=(unsigned int value)
Definition bsls_atomic.h:1945
~AtomicUint()=default
unsigned int operator++()
Definition bsls_atomic.h:1957
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdlt_iso8601util.h:691
unsigned long long Uint64
Definition bsls_types.h:137
long long Int64
Definition bsls_types.h:132