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