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