// bsls_atomicoperations.h -*-C++-*- #ifndef INCLUDED_BSLS_ATOMICOPERATIONS #define INCLUDED_BSLS_ATOMICOPERATIONS #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide platform-independent atomic operations. // //@CLASSES: // bsls::AtomicOperations: namespace for atomic operations // //@DESCRIPTION: This utility, 'bsls::AtomicOperations', provides a set of // platform-independent atomic operations for fundamental data types, such as // 32-bit integer, 64-bit integer, 32-bit unsigned integer, 64-bit unsigned // integer, pointer, and bool. The examples of provided atomic operations // include loading, storing, exchanging, incrementing and decrementing the // data of fundamental types. Atomic operations are useful for manipulating // certain types of shared data without the need for high level synchronization // mechanisms (e.g., "mutexes" or "critical sections"). // // Integer atomic operations allow for thread-safe manipulation of a single 32 // or 64-bit integer value, without the use of other synchronization // mechanisms. Even the most basic operations on data that is shared among // multiple threads must use some form of synchronization to ensure proper // results. // // Consider the prefix increment from the following snippet of C code: //.. // static int x; // ++x; //.. // Although the increment statement looks very simple, it may result in several // machine instructions. Depending on the architecture and compiler // optimization options, the statement might result in the following pseudo // machine instructions: //.. // LOAD 'x' to register // ADD 1 to register // STORE register to 'x' //.. // Consider the situation when the above statements were executed // simultaneously by two threads. Thread A could load 'x' to a register, and // then be interrupted by the operating system. Thread B could then begin to // execute, and complete all three instructions, loading, incrementing, and // storing the variable 'x'. When thread A resumes, it would increment the // value that it loaded, and store the result. // // Thus, it is possible that both threads load the same value of x to the // register, add one, and store their individual but equal results, incorrectly // incrementing 'x' by only 1 instead of the correct value 2. One could // correct this problem by using a high level synchronization mechanisms (e.g., // "mutex"), but these mechanisms are generally very expensive for such a small // fragment of code, and could result in a large number of unnecessary context // switches, for instance, if the increment statement occurs within a loop. // // Instead, an atomic operation (in this case, // 'bsls::AtomicOperations::incrementInt') can be used to manipulate the value; // use of this operation will ensure that, when executed simultaneously by // multiple threads, the threads will increment the value serially, without // interrupting one another. // // Special data types are provided to represent these values. Atomic data // types are generally the same as their corresponding primitive data types, // and therefore typically do not incur any additional memory overhead. // However, on some platforms, it may be necessary to use larger, more complex // types to represent these values; therefore they must always be accessed or // manipulated using their accessors or manipulators, respectively. Not doing // so may result in incorrect results and/or non-portable code. // // Atomic operations should not be used in situations where behavior is // inherently thread-safe and no synchronization is required; although they are // typically much faster than using high-level synchronization mechanisms to // accomplish the same results, atomic operations are typically more expensive // (in both speed and code size) than their non-atomic equivalents. // ///Memory Order and Consistency Guarantees of Atomic Operations ///------------------------------------------------------------ // Atomic operations provided by this component ensure various memory ordering // consistency guarantees. Memory ordering guarantees of atomic operations are // designed to ensure visibility and synchronization order of memory reads and // writes between threads that perform atomic operations. The operations on // objects of the provided classes ensure the most strict consistency // guarantee, sequential consistency (described below), unless explicitly // qualified with a less strict consistency guarantee (i.e., Acquire, Release, // Acquire/Release or Relaxed). // // This component implements memory order and consistency guarantees as defined // in the C++ 2011 Standard (sections: [intro.multithreaded], [atomics.order]). // // The following memory ordering guarantees are supported: //: //: o relaxed - the operation does not provide any memory consistency guarantee //: //: o release - the operation performs a release operation on the affected //: memory location, thus making preceding regular memory writes of the //: calling thread visible to other threads through the atomic variable to //: which it is applied (generally available for operations that write to a //: memory location). //: //: o acquire - the operation performs an acquire operation on the affected //: memory location, thus making regular memory writes in other threads //: released through the atomic variable to which it is applied visible to //: the current thread (generally available for operations that read from a //: memory location). //: //: o acquire/release - the operation has both acquire and release semantics //: (generally available for operations that both read and write a memory //: location). //: //: o sequential consistency - the operation has both acquire and release //: guarantees, and further guarantees that all sequentially consistent //: operations performed by the process will be observed to occur in a single //: global total order (regardless of the thread from which they are //: observed). // ///Acquire and Release Memory Consistency Guarantees ///- - - - - - - - - - - - - - - - - - - - - - - - - // Operations providing acquire and release guarantees are essential to // synchronizing the memory state between multiple threads. For example, // consider two threads, A and B, that perform store and load operations to // shared memory locations. Without any synchronization, store operations in // thread A can be freely reordered with load operations in thread B, i.e, // thread A can perform two store operations to two memory locations in a // certain order and thread B can see those operations done in a different // order due to such effects as: compiler or processor optimizations of store // and load operations, and cache synchronization between processors and cores. // // However, stores in thread A can be ordered with loads in thread B using a // combination of store-release and load-acquire operations. A store-release // operation in thread A followed by a load-acquire operation in thread B to // the *same* *memory* *location* guarantees that thread B sees all other // stores done in thread A prior to the store-release operation. The // store-release in thread A effectively synchronizes the memory state with the // load-acquire in thread B. // // An acquire-release operation is a load-modify-store operation that, if // performed in both threads A and B on the same memory location, synchronizes // stores and loads between threads A and B in both directions. // ///Sequential Consistency Memory Consistency Guarantee ///- - - - - - - - - - - - - - - - - - - - - - - - - - // Finally, load and store operations with sequential consistency are // guaranteed to performed in a global total order among all threads in the // process. To illustrate the total order, let's consider the so-called // "independent reads of independent writes" example: //.. // bsls::AtomicInt x(0); // bsls::AtomicInt y(0); // int r1, r2, r3, r4; // // void thread1() { // x = 1; // sequential consistency store // } // // void thread2() { // y = 1; // sequential consistency store // } // // void thread3() { // r1 = x; // sequential consistency load // r2 = y; // sequential consistency load // } // // void thread4() { // r3 = y; // sequential consistency load // r4 = x; // sequential consistency load // } //.. // Where 'threadN' functions are executed concurrently by different threads // (note that values 'x' and 'y' are written by independent threads). // Sequential consistency guarantees that if 'thread3' observes values 'x' and // 'y' as 'r1 == 1 && r2 == 0', then 'thread4' can't observe values 'x' and 'y' // in a different order, i.e., 'r3 == 1 && r4 == 0'. // ///Atomic Integer Operations ///------------------------- // The atomic integer operations provide thread-safe access for 32- or 64-bit // signed integer numbers without the use of higher level synchronization // mechanisms. Atomic integers are most commonly used to manipulate shared // counters and indices. Five types of operations are provided; get/set, // increment/decrement, add, swap, and test and swap. Two sub-types of // manipulators are provided for increment/decrement and addition operations. // // 'bsls::AtomicOperations' functions whose names end in "Nv" (stands for "new // value"; e.g., 'addIntNv', 'incrementInt64Nv') return the resulting value of // the operations; those without the suffix do not return a value. If an // application does not require the resulting value of an operation, it should // not use the "Nv" manipulator. On some platforms, it may be less efficient // to determine the resulting value of an operation than to simply perform the // operation. // ///Atomic Pointer Operations ///------------------------- // The atomic pointer operations provide thread-safe access to pointer values // without the use of higher level synchronization mechanisms. They are // commonly used to create fast thread-safe singly-linked lists. // ///Usage ///----- // This section illustrates intended use of this component. // ///Example 1: Usage Statistics on a Thread Pool /// - - - - - - - - - - - - - - - - - - - - - - // This example demonstrates a common use of atomic integer types for // statistics counters. The program creates a series of threads to process // transactions. As each thread completes a transaction, it atomically // increments the transaction counters. // // For this example, we assume the existence of the functions // 'processNextTransaction', 'createWorkerThread', and 'waitAllThreads'. The // function 'createWorkerThread' spawns a new thread, which executes the // 'workerThread' function. 'waitAllThreads' blocks until all the worker // thread complete. // // First, we declare the shared counters: //.. // static bsls::AtomicOperations::AtomicTypes::Int64 transactionCount; // static bsls::AtomicOperations::AtomicTypes::Int64 successCount; // static bsls::AtomicOperations::AtomicTypes::Int64 failureCount; //.. // Next, for each transaction processed, we atomically increment either the // success or the failure counter as well as the total transaction count: //.. // static void workerThread(int *stop) // { // while (!(*stop)) { // if (processNextTransaction()) { // bsls::AtomicOperations::incrementInt64(&failureCount); // } // else { // bsls::AtomicOperations::incrementInt64(&successCount); // } // bsls::AtomicOperations::incrementInt64(&transactionCount); // } // } //.. // Finally, we write function, 'serverMain', that provides the overall control // logic for the server. This function spawns the threads and then waits for // all work to be completed; when all of the threads have finished, this // function returns normally: //.. // void serverMain() // { // const int numThreads = 10; //.. // Before any of the counters is used, they must be initialized. 'initInt64' // is called to initialize each value to 0: //.. // bsls::AtomicOperations::initInt64(&transactionCount, 0); // bsls::AtomicOperations::initInt64(&successCount, 0); // bsls::AtomicOperations::initInt64(&failureCount, 0); //.. // Spawn the threads to process the transactions concurrently: //.. // for (int i = 0; i < numThreads; ++i) { // createWorkerThread(); // } //.. // Wait for all the threads to complete: //.. // waitAllThreads(); // } //.. // Note that functions 'createWorkerThread' and 'waitAllThreads' can be // implemented using any thread-support package. // ///Example 2: Thread-Safe Counted Handle ///- - - - - - - - - - - - - - - - - - - // The following example demonstrates the use of atomic integer operations to // implement a thread-safe ref-counted handle similar to a shared pointer. // Each handle (of type 'my_CountedHandle') maintains a pointer to a // representation object, 'my_CountedHandleRep', which in turn, stores both a // pointer to the managed object and a reference counter. // // Both the handle class and the representation class are template classes with // two template parameters. The template parameter, 'INSTANCE', represents the // type of the "instance", or managed object. // // A representation object can be shared by several handle objects. When a // handle object is assigned to a second handle object, the address of the // representation is copied to the second handle, and the reference count on // the representation is atomically incremented. When a handle releases its // reference to the representation, it atomically decrements the reference // count. If the resulting reference count becomes 0 (and there are no more // references to the object), the handle deletes the representation object and // the representation object, in turn, deletes the managed object ('INSTANCE'). // ///Class 'my_CountedHandleRep' ///- - - - - - - - - - - - - - // First, we define class 'my_CountedHandleRep'. This class manages a single // 'INSTANCE' object on behalf of multiple "handle" objects; since different // "handle" objects may be active in different threads, class // 'my_CountedHandleRep' must be (fully) thread-safe. Specifically, methods // 'increment' and 'decrement' must work atomically. // // Note that, this rep class is intended to be used only by class // 'my_CountedHandle', and thus all methods of class 'my_CountedHandleRep' are // declared private, and 'friend' status is granted to class // 'my_CountedHandle': //.. // // ========================= // // class my_CountedHandleRep // // ========================= // // template <class INSTANCE> // class my_CountedHandle; // // template <class INSTANCE> // class my_CountedHandleRep { // // // DATA // bsls::AtomicOperations::AtomicTypes::Int // d_count; // number of active references // INSTANCE *d_instance_p; // address of managed instance // // // FRIENDS // friend class my_CountedHandle<INSTANCE>; // // private: // not implemented // my_CountedHandleRep(const my_CountedHandleRep&); // my_CountedHandleRep& operator=(const my_CountedHandleRep&); // // public: // // CLASS METHODS // static void // deleteObject(my_CountedHandleRep<INSTANCE> *object); // // // CREATORS // my_CountedHandleRep(INSTANCE *instance); // ~my_CountedHandleRep(); // // // MANIPULATORS // void increment(); // int decrement(); // }; //.. // ///Class 'my_CountedHandle' ///- - - - - - - - - // Then, we create class 'my_CountedHandle' that provides an individual handle // to the shared, reference-counted object. Each 'my_CountedHandle' object // acts as a smart pointer, supplying an overloaded 'operator->' that provides // access to the underlying 'INSTANCE' object via pointer semantics. // // 'my_CountedHandle' can also be copied freely; the copy constructor will use // the 'increment' method from 'my_CountedHandleRep' to note the extra copy. // Similarly, the destructor will call 'my_CountedHandleRep::decrement' to note // that there is one fewer handle the underlying 'INSTANCE' has, and delete the // "rep" object when its reference count is reduced to zero: //.. // // ====================== // // class my_CountedHandle // // ====================== // // template <class INSTANCE> // class my_CountedHandle { // // // DATA // my_CountedHandleRep<INSTANCE> *d_rep_p; // shared rep. // // public: // // CREATORS // my_CountedHandle(INSTANCE *instance); // // my_CountedHandle(const my_CountedHandle<INSTANCE>& other); // // ~my_CountedHandle(); // // // ACCESSORS // INSTANCE *operator->() const; // int numReferences() const; // }; //.. // ///Function Definitions for 'my_CountedHandleRep' ///- - - - - - - - - - - - - - - - // Next, we provide a definition for the 'static' 'deleteObject' method, which // is called by the destructor for class 'my_CountedHandle' for the last // instance of 'my_CountedHandle' using the given "rep" object: //.. // template <class INSTANCE> // inline // void my_CountedHandleRep<INSTANCE>::deleteObject( // my_CountedHandleRep<INSTANCE> *object) // { // delete object; // } //.. // Then, we write the constructor for the 'my_CountedHandleRep<INSTANCE>' // class. We initialize the atomic reference counter to one reference using // 'bsls::AtomicOperations::initInt'. This reflects the fact that this // constructor will be called by a new instance of 'my_CountedHandle'. That // instance is our first and only handle when this constructor is called: //.. // template <class INSTANCE> // inline // my_CountedHandleRep<INSTANCE>:: // my_CountedHandleRep(INSTANCE *instance) // : d_instance_p(instance) // { // bsls::AtomicOperations::initInt(&d_count, 1); // } //.. // Then, we define the destructor, which just deletes 'my_CountedHandle' // 'd_instance_p': //.. // template <class INSTANCE> // inline // my_CountedHandleRep<INSTANCE>::~my_CountedHandleRep() // { // delete d_instance_p; // } //.. // Next, we define method 'increment', which atomically increments the number // of references to this 'my_CountedHandleRep'. Since our caller is not // interested in the result (and our return type is thus 'void'), we use // 'incrementInt' instead of 'incrementIntNv'. //.. // // MANIPULATORS // template <class INSTANCE> // inline // void my_CountedHandleRep<INSTANCE>::increment() // { // bsls::AtomicOperations::incrementInt(&d_count); // } //.. // Then, we implement method 'decrement', which atomically decrements the // reference count; since our caller will need to check the resulting value to // determine whether the 'INSTANCE' should be deleted, we use 'decrementIntNv' // rather than 'decrementInt', and return the new number of references: //.. // template <class INSTANCE> // inline // int my_CountedHandleRep<INSTANCE>::decrement() // { // return bsls::AtomicOperations::decrementIntNv(&d_count); // } //.. // ///Function Definitions for 'my_CountedHandle' ///- - - - - - - - - - - - - - - // Next, we define the first constructor for 'my_CountedHandle', which is used // when creating a handle for a new 'INSTANCE'; note that the 'INSTANCE' is // constructed separately, and a pointer to that object is passed as the first // argument ('object'): //.. // // ---------------------- // // class my_CountedHandle // // ---------------------- // // template <class INSTANCE> // inline // my_CountedHandle<INSTANCE>::my_CountedHandle(INSTANCE *instance) // { // d_rep_p = new my_CountedHandleRep<INSTANCE>(instance); // } //.. // Then, we define the copy constructor; the new object copies the underlying // 'my_CountedHandleRep' and then increments its counter: //.. // template <class INSTANCE> // inline // my_CountedHandle<INSTANCE>::my_CountedHandle( // const my_CountedHandle<INSTANCE>& other) // : d_rep_p(other.d_rep_p) // { // if (d_rep_p) { // d_rep_p->increment(); // } // } //.. // Next, we define the destructor that decrements the "rep" object's reference // count using the 'decrement' method. The 'decrement' method returns the // object's reference count after the decrement is completed, and // 'my_CountedHandle' uses this value to determine whether the "rep" object // should be deleted: //.. // template <class INSTANCE> // inline // my_CountedHandle<INSTANCE>::~my_CountedHandle() // { // if (d_rep_p && 0 == d_rep_p->decrement()) { // my_CountedHandleRep<INSTANCE>::deleteObject(d_rep_p); // } // } //.. // Now, we define member 'operator->()', which provides basic pointer semantics // for 'my_CountedHandle': //.. // template <class INSTANCE> // inline // INSTANCE *my_CountedHandle<INSTANCE>::operator->() const // { // return d_rep_p->d_instance_p; // } //.. // Finally, we define method 'numReferences', which returns the value of the // reference counter: //.. // template <class INSTANCE> // inline // int my_CountedHandle<INSTANCE>::numReferences() const // { // return d_rep_p ? bsls::AtomicOperations::getInt(d_rep_p->d_count) : 0; // } //.. // Note that, while class 'my_CountedHandleRep' is itself fully thread-safe, it // does not guarantee thread safety for the 'INSTANCE' object. In order to // provide thread safety for the 'INSTANCE' in the general case, the "rep" // would need to use a more general concurrency mechanism such as a mutex. // ///Example 3: Thread-Safe Lock-Free Singly-Linked List ///- - - - - - - - - - - - - - - - - - - - - - - - - - // This example demonstrates the use of atomic pointers to implement a fast and // thread-aware, yet fast single-linked list. The example class, // 'my_PtrStack', is a templatized pointer stack, supporting 'push' and 'pop' // methods. The class is implemented using a single-linked list. Nodes in the // list are linked together using atomic operations. Instance of this // structure are allocated using the provided allocator. When nodes are freed, // they are cached on a free list. This free list is also implemented as a // single-linked list, using atomic pointer operations. // // First, we create class template, 'my_PtrStack', parameterized by 'TYPE'. // Instances of this template maintain a list of nodes and a free-node list. // Each node has a pointer to a data item, 'd_item_p', a link to the next node // in the list, 'd_next_p'. The definition of the 'my_PtrStack' class is // provided below: //.. // template <class TYPE> // class my_PtrStack { // // TYPES // struct Node { // TYPE *d_item_p; // Node *d_next_p; // }; // // // DATA // bsls::AtomicOperations::AtomicTypes::Pointer d_list_p; // bsls::AtomicOperations::AtomicTypes::Pointer d_freeList_p; // // // PRIVATE MANIPULATORS // Node *allocateNode(); // void freeNode(Node *node); // void deleteNodes(Node *node); // // public: // // CREATORS // my_PtrStack(); // ~my_PtrStack(); // // // MANIPULATORS // void push(TYPE *item); // TYPE *pop(); // }; //.. // Then, we write the constructor that initializes the pointers for the node // list and the free list: //.. // // CREATORS // template <class TYPE> // inline my_PtrStack<TYPE>::my_PtrStack() // { // bsls::AtomicOperations::initPointer(&d_freeList_p, 0); // bsls::AtomicOperations::initPointer(&d_list_p, 0); // } //.. // Next, we define the 'deleteNodes' and the destructor function to delete // nodes that the 'my_PtrStack' object owns. Note that we don't need to worry // about the concurrent access to node lists in the destructor, as destructor // can be executed in only a single thread: //.. // template <class TYPE> // inline void my_PtrStack<TYPE>::deleteNodes(Node *node) // { // while (node) { // Node *next = node->d_next_p; // delete node; // node = next; // } // } // // template <class TYPE> // inline my_PtrStack<TYPE>::~my_PtrStack() // { // deleteNodes( // (Node *) bsls::AtomicOperations::getPtrRelaxed(&d_list_p)); // deleteNodes( // (Node *) bsls::AtomicOperations::getPtrRelaxed(&d_freeList_p)); // } //.. // Then, we define method 'allocateNode' to get a node from the free list in // the thread-safe manner by leveraging atomic operations to ensure proper // thread synchronization: //.. // // PRIVATE MANIPULATORS // template <class TYPE> // inline typename my_PtrStack<TYPE>::Node *my_PtrStack<TYPE>::allocateNode() // { // Node *node; //.. // To remove an item from this list, get the current list head using 'getPtr'. // Then, test and swap it with the next node. 'testAndSwapPtr' compares // 'd_freeList_p' to 'node', replacing it with 'node->d_next_p' only if it // matches. If 'd_freeList_p' did not match 'node', then the free list has // been changed on another thread, between the calls to 'getPtr' and // 'testAndSwapPtr'. If the list head has changed, then try again: //.. // do { // node = (Node*) bsls::AtomicOperations::getPtr(&d_freeList_p); // if (!node) break; // } while (bsls::AtomicOperations::testAndSwapPtr( // &d_freeList_p, // node, // node->d_next_p) != node); //.. // Next, we allocate a new node if there are no nodes in the free node list: //.. // if (!node) { // node = new Node(); // } // return node; // } //.. // Then, we provide the 'freeNode' method to add a given 'node' to the free // list. To add the node to the list, we set the next pointer of the new node // to the current value of the list head, and atomically test and swap the head // of the list with the new node. If the list head has been changed (by // another thread), we try again: //.. // template <class TYPE> // inline void my_PtrStack<TYPE>::freeNode(Node *node) // { // do { // node->d_next_p = (Node*) bsls::AtomicOperations::getPtr( // &d_freeList_p); // } while (bsls::AtomicOperations::testAndSwapPtr( // &d_freeList_p, // node->d_next_p, // node) != node->d_next_p); // } //.. // Now, we begin to define the public "stack-like" interface for 'my_PtrStack'. // Note that the 'push' method is similar to 'freeNode', except that it assigns // an item value and operates on 'd_list_p', which maintains the list of active // nodes: //.. // template <class TYPE> // inline void my_PtrStack<TYPE>::push(TYPE *item) // { // Node *node = allocateNode(); // node->d_item_p = item; // do { // node->d_next_p = (Node*) bsls::AtomicOperations::getPtr(&d_list_p); // } while (bsls::AtomicOperations::testAndSwapPtr( // &d_list_p, // node->d_next_p, // node)!= node->d_next_p); // } //.. // Finally, we define the 'pop' method that removes the node from the top of // active node list, 'd_list_p', adds it to the free-node list, and returns the // data item contained in the node to the caller: //.. // template <class TYPE> // inline TYPE *my_PtrStack<TYPE>::pop() // { // Node *node; // do { // node = (Node*) bsls::AtomicOperations::getPtr(&d_list_p); // if (!node) break; // } while (bsls::AtomicOperations::testAndSwapPtr( // &d_freeList_p, // node, // node->d_next_p)!= node); // TYPE *item = node ? node->d_item_p : 0; // if (node) // freeNode(node); // return item; // } //.. // Notice that if the stack was empty, a NULL pointer is returned. #include <bsls_platform.h> #include <bsls_types.h> #if defined(BSLS_PLATFORM_CMP_CLANG) #if __has_extension(c_atomic) || __has_extension(cxx_atomic) // clang 3.1+ #define BSLS_ATOMICOPERATIONS_CLANG_ATOMICS #endif #endif #if defined(BSLS_ATOMICOPERATIONS_CLANG_ATOMICS) // clang 3.1+ # include <bsls_atomicoperations_all_all_clangintrinsics.h> #elif defined(BSLS_PLATFORM_CMP_GNU) && BSLS_PLATFORM_CMP_VERSION >= 40700 // GCC 4.7+ # include <bsls_atomicoperations_all_all_gccintrinsics.h> #elif defined(BSLS_PLATFORM_CPU_X86) # if defined(BSLS_PLATFORM_CMP_GNU) || defined(BSLS_PLATFORM_CMP_CLANG) # include <bsls_atomicoperations_x86_all_gcc.h> # elif defined(BSLS_PLATFORM_CMP_MSVC) # include <bsls_atomicoperations_x86_win_msvc.h> # else # define BSLS_ATOMICOPERATIONS_ERROR # endif #elif defined(BSLS_PLATFORM_CPU_X86_64) # if defined(BSLS_PLATFORM_CMP_GNU) || defined(BSLS_PLATFORM_CMP_CLANG) # include <bsls_atomicoperations_x64_all_gcc.h> # elif defined(BSLS_PLATFORM_CMP_MSVC) # include <bsls_atomicoperations_x64_win_msvc.h> # else # define BSLS_ATOMICOPERATIONS_ERROR # endif #elif defined(BSLS_PLATFORM_CPU_POWERPC) # if defined(BSLS_PLATFORM_CMP_IBM) # if defined(BSLS_PLATFORM_CPU_64_BIT) # include <bsls_atomicoperations_powerpc64_aix_xlc.h> # else # include <bsls_atomicoperations_powerpc32_aix_xlc.h> # endif # elif defined(BSLS_PLATFORM_CMP_GNU) # include <bsls_atomicoperations_powerpc_all_gcc.h> # else # define BSLS_ATOMICOPERATIONS_ERROR # endif #elif defined(BSLS_PLATFORM_CPU_SPARC_32) \ && (defined(BSLS_PLATFORM_CMP_GNU) || defined(BSLS_PLATFORM_CMP_SUN)) # include <bsls_atomicoperations_sparc32_sun_cc.h> #elif defined(BSLS_PLATFORM_CPU_SPARC_V9) \ && (defined(BSLS_PLATFORM_CMP_GNU) || defined(BSLS_PLATFORM_CMP_SUN)) # include <bsls_atomicoperations_sparc64_sun_cc.h> #elif defined(BSLS_PLATFORM_CPU_ARM) # if defined(BSLS_PLATFORM_CMP_GNU) || defined(BSLS_PLATFORM_CMP_CLANG) # include <bsls_atomicoperations_arm_all_gcc.h> # else # define BSLS_ATOMICOPERATIONS_ERROR # endif #else # define BSLS_ATOMICOPERATIONS_ERROR #endif #if defined(BSLS_ATOMICOPERATIONS_ERROR) # error "no implementation of atomics found for this platform" #endif namespace BloombergLP { namespace bsls { // ======================= // struct AtomicOperations // ======================= struct AtomicOperations { // 'AtomicOperations' provides a namespace for a suite of atomic operations // on the following types as defined by the 'AtomicTypes' typedef: // integer - 'AtomicTypes::Int', 64bit integer - 'AtomicTypes::Int64', // pointer - 'AtomicTypes::Pointer'. // TYPES typedef AtomicOperations_Imp Imp; typedef Atomic_TypeTraits<Imp> AtomicTypes; // *** atomic functions for int *** // CLASS METHODS static int getInt(AtomicTypes::Int const *atomicInt); // Atomically retrieve the value of the specified 'atomicInt', // providing the sequential consistency memory ordering guarantee. static int getIntAcquire(AtomicTypes::Int const *atomicInt); // Atomically retrieve the value of the specified 'atomicInt', // providing the acquire memory ordering guarantee. static int getIntRelaxed(AtomicTypes::Int const *atomicInt); // Atomically retrieve the value of the specified 'atomicInt', without // providing any memory ordering guarantees. static void initInt(AtomicTypes::Int *atomicInt, int initialValue = 0); // Initialize the specified 'atomicInt' and set its value to the // optionally specified 'initialValue'. static void setInt(AtomicTypes::Int *atomicInt, int value); // Atomically set the value of the specified 'atomicInt' to the // specified 'value', providing the sequential consistency memory // ordering guarantee. static void setIntRelaxed(AtomicTypes::Int *atomicInt, int value); // Atomically set the value of the specified 'atomicInt' to the // specified 'value', without providing any memory ordering guarantees. static void setIntRelease(AtomicTypes::Int *atomicInt, int value); // Atomically set the value of the specified 'atomicInt' to the // specified 'value', providing the release memory ordering guarantee. static int swapInt(AtomicTypes::Int *atomicInt, int swapValue); // Atomically set the value of the specified 'atomicInt' to the // specified 'swapValue', and return its previous value, providing the // sequential consistency memory ordering guarantee. static int swapIntAcqRel(AtomicTypes::Int *atomicInt, int swapValue); // Atomically set the value of the specified 'atomicInt' to the // specified 'swapValue', and return its previous value, providing the // acquire/release memory ordering guarantee. static int testAndSwapInt(AtomicTypes::Int *atomicInt, int compareValue, int swapValue); // Conditionally set the value of the specified 'atomicInt' to the // specified 'swapValue' if and only if the value of 'atomicInt' equals // the value of the specified 'compareValue', and return the initial // value of 'atomicInt', providing the sequential consistency memory // ordering guarantee. The whole operation is performed atomically. static int testAndSwapIntAcqRel(AtomicTypes::Int *atomicInt, int compareValue, int swapValue); // Conditionally set the value of the specified 'atomicInt' to the // specified 'swapValue' if and only if the value of 'atomicInt' equals // the value of the specified 'compareValue', and return the initial // value of 'atomicInt', providing the acquire/release memory ordering // guarantee. The whole operation is performed atomically. static void addInt(AtomicTypes::Int *atomicInt, int value); // Atomically add to the specified 'atomicInt' the specified 'value', // providing the sequential consistency memory ordering guarantee. static void addIntAcqRel(AtomicTypes::Int *atomicInt, int value); // Atomically add to the specified 'atomicInt' the specified 'value', // providing the acquire/release memory ordering guarantee. static void addIntRelaxed(AtomicTypes::Int *atomicInt, int value); // Atomically add to the specified 'atomicInt' the specified 'value', // without providing any memory ordering guarantees. static int addIntNv(AtomicTypes::Int *atomicInt, int value); // Atomically add to the specified 'atomicInt' the specified 'value' // and return the resulting value, providing the sequential consistency // memory ordering guarantee. static int addIntNvAcqRel(AtomicTypes::Int *atomicInt, int value); // Atomically add to the specified 'atomicInt' the specified 'value' // and return the resulting value, providing the acquire/release memory // ordering guarantee. static int addIntNvRelaxed(AtomicTypes::Int *atomicInt, int value); // Atomically add to the specified 'atomicInt' the specified 'value' // and return the resulting value, without providing any memory // ordering guarantees. static void decrementInt(AtomicTypes::Int *atomicInt); // Atomically decrement the value of the specified 'atomicInt' by 1, // providing the sequential consistency memory ordering guarantee. static void decrementIntAcqRel(AtomicTypes::Int *atomicInt); // Atomically decrement the value of the specified 'atomicInt' by 1, // providing the acquire/release memory ordering guarantee. static int decrementIntNv(AtomicTypes::Int *atomicInt); // Atomically decrement the specified 'atomicInt' by 1 and return the // resulting value, providing the sequential consistency memory // ordering guarantee. static int decrementIntNvAcqRel(AtomicTypes::Int *atomicInt); // Atomically decrement the specified 'atomicInt' by 1 and return the // resulting value, providing the acquire/release memory ordering // guarantee. static void incrementInt(AtomicTypes::Int *atomicInt); // Atomically increment the value of the specified 'atomicInt' by 1, // providing the sequential consistency memory ordering guarantee. static void incrementIntAcqRel(AtomicTypes::Int *atomicInt); // Atomically increment the value of the specified 'atomicInt' by 1, // providing the acquire/release memory ordering guarantee. static int incrementIntNv(AtomicTypes::Int *atomicInt); // Atomically increment the specified 'atomicInt' by 1 and return the // resulting value, providing the sequential consistency memory // ordering guarantee. static int incrementIntNvAcqRel(AtomicTypes::Int *atomicInt); // Atomically increment the specified 'atomicInt' by 1 and return the // resulting value, providing the acquire/release memory ordering // guarantee. static int subtractIntNv(AtomicTypes::Int *atomicInt,int value); // Atomically subtract from the specified 'atomicInt' the specified // 'value' and return the resulting value, providing the sequential // consistency memory ordering guarantee. static int subtractIntNvAcqRel(AtomicTypes::Int *atomicInt, int value); // Atomically subtract from the specified 'atomicInt' the specified // 'value' and return the resulting value, providing the // acquire/release memory ordering guarantee. static int subtractIntNvRelaxed(AtomicTypes::Int *atomicInt, int value); // Atomically subtract from the specified 'atomicInt' the specified // 'value' and return the resulting value, without providing any memory // ordering guarantees. // *** atomic functions for Int64 *** static Types::Int64 getInt64(AtomicTypes::Int64 const *atomicInt); // Atomically retrieve the value of the specified 'atomicInt', // providing the sequential consistency memory ordering guarantee. static Types::Int64 getInt64Acquire(AtomicTypes::Int64 const *atomicInt); // Atomically retrieve the value of the specified 'atomicInt', // providing the acquire memory ordering guarantee. static Types::Int64 getInt64Relaxed(AtomicTypes::Int64 const *atomicInt); // Atomically retrieve the value of the specified 'atomicInt', without // providing any memory ordering guarantees. static void initInt64(AtomicTypes::Int64 *atomicInt, Types::Int64 initialValue = 0); // Initialize the specified 'atomicInt' and set its value to the // optionally specified 'initialValue'. static void setInt64(AtomicTypes::Int64 *atomicInt, Types::Int64 value); // Atomically set the value of the specified 'atomicInt' to the // specified 'value', providing the sequential consistency memory // ordering guarantee. static void setInt64Relaxed(AtomicTypes::Int64 *atomicInt, Types::Int64 value); // Atomically set the value of the specified 'atomicInt' to the // specified 'value', without providing any memory ordering guarantees. static void setInt64Release(AtomicTypes::Int64 *atomicInt, Types::Int64 value); // Atomically set the value of the specified 'atomicInt' to the // specified 'value', providing the release memory ordering guarantee. static Types::Int64 swapInt64(AtomicTypes::Int64 *atomicInt, Types::Int64 swapValue); // Atomically set the value of the specified 'atomicInt' to the // specified 'swapValue' and return its previous value, providing the // sequential consistency memory ordering guarantee. static Types::Int64 swapInt64AcqRel(AtomicTypes::Int64 *atomicInt, Types::Int64 swapValue); // Atomically set the value of the specified 'atomicInt' to the // specified 'swapValue' and return its previous value, providing the // acquire/release memory ordering guarantee. static Types::Int64 testAndSwapInt64(AtomicTypes::Int64 *atomicInt, Types::Int64 compareValue, Types::Int64 swapValue); // Conditionally set the value of the specified 'atomicInt' to the // specified 'swapValue' if and only if the value of 'atomicInt' equals // the value of the specified 'compareValue', and return the initial // value of 'atomicInt', providing the sequential consistency memory // ordering guarantee. The whole operation is performed atomically. static Types::Int64 testAndSwapInt64AcqRel( AtomicTypes::Int64 *atomicInt, Types::Int64 compareValue, Types::Int64 swapValue); // Conditionally set the value of the specified 'atomicInt' to the // specified 'swapValue' if and only if the value of 'atomicInt' equals // the value of the specified 'compareValue', and return the initial // value of 'atomicInt', providing the acquire/release memory ordering // guarantee. The whole operation is performed atomically. static void addInt64(AtomicTypes::Int64 *atomicInt, Types::Int64 value); // Atomically add to the specified 'atomicInt' the specified 'value', // providing the sequential consistency memory ordering guarantee. static void addInt64AcqRel(AtomicTypes::Int64 *atomicInt, Types::Int64 value); // Atomically add to the specified 'atomicInt' the specified 'value', // providing the acquire/release memory ordering guarantee. static void addInt64Relaxed(AtomicTypes::Int64 *atomicInt, Types::Int64 value); // Atomically add to the specified 'atomicInt' the specified 'value', // without providing any memory ordering guarantees. static Types::Int64 addInt64Nv(AtomicTypes::Int64 *atomicInt, Types::Int64 value); // Atomically add to the specified 'atomicInt' the specified 'value' // and return the resulting value, providing the sequential consistency // memory ordering guarantee. static Types::Int64 addInt64NvAcqRel(AtomicTypes::Int64 *atomicInt, Types::Int64 value); // Atomically add to the specified 'atomicInt' the specified 'value' // and return the resulting value, providing the acquire/release memory // ordering guarantee. static Types::Int64 addInt64NvRelaxed(AtomicTypes::Int64 *atomicInt, Types::Int64 value); // Atomically add to the specified 'atomicInt' the specified 'value' // and return the resulting value, without providing any memory // ordering guarantees. static void decrementInt64(AtomicTypes::Int64 *atomicInt); // Atomically decrement the specified 'atomicInt' by 1, providing the // sequential consistency memory ordering guarantee. static void decrementInt64AcqRel(AtomicTypes::Int64 *atomicInt); // Atomically decrement the specified 'atomicInt' by 1, providing the // acquire/release memory ordering guarantee. static Types::Int64 decrementInt64Nv(AtomicTypes::Int64 *atomicInt); // Atomically decrement the specified 'atomicInt' by 1 and return the // resulting value, providing the sequential consistency memory // ordering guarantee. static Types::Int64 decrementInt64NvAcqRel(AtomicTypes::Int64 *atomicInt); // Atomically decrement the specified 'atomicInt' by 1 and return the // resulting value, providing the acquire/release memory ordering // guarantee. static void incrementInt64(AtomicTypes::Int64 *atomicInt); // Atomically increment the value of the specified 'atomicInt' by 1, // providing the sequential consistency memory ordering guarantee. static void incrementInt64AcqRel(AtomicTypes::Int64 *atomicInt); // Atomically increment the value of the specified 'atomicInt' by 1, // providing the acquire/release memory ordering guarantee. static Types::Int64 incrementInt64Nv(AtomicTypes::Int64 *atomicInt); // Atomically increment the specified 'atomicInt' by 1 and return the // resulting value, providing the sequential consistency memory // ordering guarantee. static Types::Int64 incrementInt64NvAcqRel(AtomicTypes::Int64 *atomicInt); // Atomically increment the specified 'atomicInt' by 1 and return the // resulting value, providing the acquire/release memory ordering // guarantee. static Types::Int64 subtractInt64Nv(AtomicTypes::Int64 *atomicInt, Types::Int64 value); // Atomically subtract from the specified 'atomicInt' the specified // 'value' and return the resulting value, providing the sequential // consistency memory ordering guarantee. static Types::Int64 subtractInt64NvAcqRel(AtomicTypes::Int64 *atomicInt, Types::Int64 value); // Atomically subtract from the specified 'atomicInt' the specified // 'value' and return the resulting value, providing the // acquire/release memory ordering guarantee. static Types::Int64 subtractInt64NvRelaxed(AtomicTypes::Int64 *atomicInt, Types::Int64 value); // Atomically subtract from the specified 'atomicInt' the specified // 'value' and return the resulting value, without providing any memory // ordering guarantees. // *** atomic functions for unsigned int *** // CLASS METHODS static unsigned int getUint(AtomicTypes::Uint const *atomicUint); // Atomically retrieve the value of the specified 'atomicUint', // providing the sequential consistency memory ordering guarantee. static unsigned int getUintAcquire(AtomicTypes::Uint const *atomicUint); // Atomically retrieve the value of the specified 'atomicUint', // providing the acquire memory ordering guarantee. static unsigned int getUintRelaxed(AtomicTypes::Uint const *atomicUint); // Atomically retrieve the value of the specified 'atomicUint', without // providing any memory ordering guarantees. static void initUint(AtomicTypes::Uint *atomicUint, unsigned int initialValue = 0); // Initialize the specified 'atomicUint' and set its value to the // optionally specified 'initialValue'. static void setUint(AtomicTypes::Uint *atomicUint, unsigned int value); // Atomically set the value of the specified 'atomicUint' to the // specified 'value', providing the sequential consistency memory // ordering guarantee. static void setUintRelaxed(AtomicTypes::Uint *atomicUint, unsigned int value); // Atomically set the value of the specified 'atomicUint' to the // specified 'value', without providing any memory ordering guarantees. static void setUintRelease(AtomicTypes::Uint *atomicUint, unsigned int value); // Atomically set the value of the specified 'atomicUint' to the // specified 'value', providing the release memory ordering guarantee. static unsigned int swapUint(AtomicTypes::Uint *atomicUint, unsigned int swapValue); // Atomically set the value of the specified 'atomicUint' to the // specified 'swapValue', and return its previous value, providing the // sequential consistency memory ordering guarantee. static unsigned int swapUintAcqRel(AtomicTypes::Uint *atomicUint, unsigned int swapValue); // Atomically set the value of the specified 'atomicUint' to the // specified 'swapValue', and return its previous value, providing the // acquire/release memory ordering guarantee. static unsigned int testAndSwapUint(AtomicTypes::Uint *atomicUint, unsigned int compareValue, unsigned int swapValue); // Conditionally set the value of the specified 'atomicUint' to the // specified 'swapValue' if and only if the value of 'atomicUint' // equals the value of the specified 'compareValue', and return the // initial value of 'atomicUint', providing the sequential consistency // memory ordering guarantee. The whole operation is performed // atomically. static unsigned int testAndSwapUintAcqRel(AtomicTypes::Uint *atomicUint, unsigned int compareValue, unsigned int swapValue); // Conditionally set the value of the specified 'atomicUint' to the // specified 'swapValue' if and only if the value of 'atomicInt' equals // the value of the specified 'compareValue', and return the initial // value of 'atomicUint', providing the acquire/release memory ordering // guarantee. The whole operation is performed atomically. static void addUint(AtomicTypes::Uint *atomicUint, unsigned int value); // Atomically add to the specified 'atomicUint' the specified 'value', // providing the sequential consistency memory ordering guarantee. static void addUintAcqRel(AtomicTypes::Uint *atomicUint, unsigned int value); // Atomically add to the specified 'atomicUint' the specified 'value', // providing the acquire/release memory ordering guarantee. static void addUintRelaxed(AtomicTypes::Uint *atomicUint, unsigned int value); // Atomically add to the specified 'atomicUint' the specified 'value', // without providing any memory ordering guarantees. static unsigned int addUintNv(AtomicTypes::Uint *atomicUint, unsigned int value); // Atomically add to the specified 'atomicUint' the specified 'value' // and return the resulting value, providing the sequential consistency // memory ordering guarantee. static unsigned int addUintNvAcqRel(AtomicTypes::Uint *atomicUint, unsigned int value); // Atomically add to the specified 'atomicUint' the specified 'value' // and return the resulting value, providing the acquire/release memory // ordering guarantee. static unsigned int addUintNvRelaxed(AtomicTypes::Uint *atomicUint, unsigned int value); // Atomically add to the specified 'atomicUint' the specified 'value' // and return the resulting value, without providing any memory // ordering guarantees. static void decrementUint(AtomicTypes::Uint *atomicUint); // Atomically decrement the value of the specified 'atomicUint' by 1, // providing the sequential consistency memory ordering guarantee. static void decrementUintAcqRel(AtomicTypes::Uint *atomicUint); // Atomically decrement the value of the specified 'atomicUint' by 1, // providing the acquire/release memory ordering guarantee. static unsigned int decrementUintNv(AtomicTypes::Uint *atomicUint); // Atomically decrement the specified 'atomicUint' by 1 and return the // resulting value, providing the sequential consistency memory // ordering guarantee. static unsigned int decrementUintNvAcqRel(AtomicTypes::Uint *atomicUint); // Atomically decrement the specified 'atomicUint' by 1 and return the // resulting value, providing the acquire/release memory ordering // guarantee. static void incrementUint(AtomicTypes::Uint *atomicUint); // Atomically increment the value of the specified 'atomicUint' by 1, // providing the sequential consistency memory ordering guarantee. static void incrementUintAcqRel(AtomicTypes::Uint *atomicUint); // Atomically increment the value of the specified 'atomicUint' by 1, // providing the acquire/release memory ordering guarantee. static unsigned int incrementUintNv(AtomicTypes::Uint *atomicUint); // Atomically increment the specified 'atomicUint' by 1 and return the // resulting value, providing the sequential consistency memory // ordering guarantee. static unsigned int incrementUintNvAcqRel(AtomicTypes::Uint *atomicUint); // Atomically increment the specified 'atomicUint' by 1 and return the // resulting value, providing the acquire/release memory ordering // guarantee. static unsigned int subtractUintNv(AtomicTypes::Uint *atomicUint, unsigned int value); // Atomically subtract from the specified 'atomicUint' the specified // 'value' and return the resulting value, providing the sequential // consistency memory ordering guarantee. static unsigned int subtractUintNvAcqRel(AtomicTypes::Uint *atomicUint, unsigned int value); // Atomically subtract from the specified 'atomicUint' the specified // 'value' and return the resulting value, providing the // acquire/release memory ordering guarantee. static unsigned int subtractUintNvRelaxed(AtomicTypes::Uint *atomicUint, unsigned int value); // Atomically subtract from the specified 'atomicUint' the specified // 'value' and return the resulting value, without providing any memory // ordering guarantees. // *** atomic functions for Uint64 *** static Types::Uint64 getUint64(AtomicTypes::Uint64 const *atomicUint); // Atomically retrieve the value of the specified 'atomicUint', // providing the sequential consistency memory ordering guarantee. static Types::Uint64 getUint64Acquire( AtomicTypes::Uint64 const *atomicUint); // Atomically retrieve the value of the specified 'atomicUint', // providing the acquire memory ordering guarantee. static Types::Uint64 getUint64Relaxed( AtomicTypes::Uint64 const *atomicUint); // Atomically retrieve the value of the specified 'atomicUint', without // providing any memory ordering guarantees. static void initUint64(AtomicTypes::Uint64 *atomicUint, Types::Uint64 initialValue = 0); // Initialize the specified 'atomicUint' and set its value to the // optionally specified 'initialValue'. static void setUint64(AtomicTypes::Uint64 *atomicUint, Types::Uint64 value); // Atomically set the value of the specified 'atomicUint' to the // specified 'value', providing the sequential consistency memory // ordering guarantee. static void setUint64Relaxed(AtomicTypes::Uint64 *atomicUint, Types::Uint64 value); // Atomically set the value of the specified 'atomicUint' to the // specified 'value', without providing any memory ordering guarantees. static void setUint64Release(AtomicTypes::Uint64 *atomicUint, Types::Uint64 value); // Atomically set the value of the specified 'atomicUint' to the // specified 'value', providing the release memory ordering guarantee. static Types::Uint64 swapUint64(AtomicTypes::Uint64 *atomicUint, Types::Uint64 swapValue); // Atomically set the value of the specified 'atomicUint' to the // specified 'swapValue' and return its previous value, providing the // sequential consistency memory ordering guarantee. static Types::Uint64 swapUint64AcqRel(AtomicTypes::Uint64 *atomicUint, Types::Uint64 swapValue); // Atomically set the value of the specified 'atomicUint' to the // specified 'swapValue' and return its previous value, providing the // acquire/release memory ordering guarantee. static Types::Uint64 testAndSwapUint64(AtomicTypes::Uint64 *atomicUint, Types::Uint64 compareValue, Types::Uint64 swapValue); // Conditionally set the value of the specified 'atomicUint' to the // specified 'swapValue' if and only if the value of 'atomicUint' // equals the value of the specified 'compareValue', and return the // initial value of 'atomicUint', providing the sequential consistency // memory ordering guarantee. The whole operation is performed // atomically. static Types::Uint64 testAndSwapUint64AcqRel( AtomicTypes::Uint64 *atomicUint, Types::Uint64 compareValue, Types::Uint64 swapValue); // Conditionally set the value of the specified 'atomicUint' to the // specified 'swapValue' if and only if the value of 'atomicUint' // equals the value of the specified 'compareValue', and return the // initial value of 'atomicUint', providing the acquire/release memory // ordering guarantee. The whole operation is performed atomically. static void addUint64(AtomicTypes::Uint64 *atomicUint, Types::Uint64 value); // Atomically add to the specified 'atomicUint' the specified 'value', // providing the sequential consistency memory ordering guarantee. static void addUint64AcqRel(AtomicTypes::Uint64 *atomicUint, Types::Uint64 value); // Atomically add to the specified 'atomicUint' the specified 'value', // providing the acquire/release memory ordering guarantee. static void addUint64Relaxed(AtomicTypes::Uint64 *atomicUint, Types::Uint64 value); // Atomically add to the specified 'atomicUint' the specified 'value', // without providing any memory ordering guarantees. static Types::Uint64 addUint64Nv(AtomicTypes::Uint64 *atomicUint, Types::Uint64 value); // Atomically add to the specified 'atomicUint' the specified 'value' // and return the resulting value, providing the sequential consistency // memory ordering guarantee. static Types::Uint64 addUint64NvAcqRel(AtomicTypes::Uint64 *atomicUint, Types::Uint64 value); // Atomically add to the specified 'atomicUint' the specified 'value' // and return the resulting value, providing the acquire/release memory // ordering guarantee. static Types::Uint64 addUint64NvRelaxed(AtomicTypes::Uint64 *atomicUint, Types::Uint64 value); // Atomically add to the specified 'atomicUint' the specified 'value' // and return the resulting value, without providing any memory // ordering guarantees. static void decrementUint64(AtomicTypes::Uint64 *atomicUint); // Atomically decrement the specified 'atomicUint' by 1, providing the // sequential consistency memory ordering guarantee. static void decrementUint64AcqRel(AtomicTypes::Uint64 *atomicUint); // Atomically decrement the specified 'atomicUint' by 1, providing the // acquire/release memory ordering guarantee. static Types::Uint64 decrementUint64Nv(AtomicTypes::Uint64 *atomicUint); // Atomically decrement the specified 'atomicUint' by 1 and return the // resulting value, providing the sequential consistency memory // ordering guarantee. static Types::Uint64 decrementUint64NvAcqRel( AtomicTypes::Uint64 *atomicUint); // Atomically decrement the specified 'atomicUint' by 1 and return the // resulting value, providing the acquire/release memory ordering // guarantee. static void incrementUint64(AtomicTypes::Uint64 *atomicUint); // Atomically increment the value of the specified 'atomicUint' by 1, // providing the sequential consistency memory ordering guarantee. static void incrementUint64AcqRel(AtomicTypes::Uint64 *atomicUint); // Atomically increment the value of the specified 'atomicUint' by 1, // providing the acquire/release memory ordering guarantee. static Types::Uint64 incrementUint64Nv(AtomicTypes::Uint64 *atomicUint); // Atomically increment the specified 'atomicUint' by 1 and return the // resulting value, providing the sequential consistency memory // ordering guarantee. static Types::Uint64 incrementUint64NvAcqRel( AtomicTypes::Uint64 *atomicUint); // Atomically increment the specified 'atomicUint' by 1 and return the // resulting value, providing the acquire/release memory ordering // guarantee. static Types::Uint64 subtractUint64Nv(AtomicTypes::Uint64 *atomicUint, Types::Uint64 value); // Atomically subtract from the specified 'atomicUint' the specified // 'value' and return the resulting value, providing the sequential // consistency memory ordering guarantee. static Types::Uint64 subtractUint64NvAcqRel( AtomicTypes::Uint64 *atomicUint, Types::Uint64 value); // Atomically subtract from the specified 'atomicUint' the specified // 'value' and return the resulting value, providing the // acquire/release memory ordering guarantee. static Types::Uint64 subtractUint64NvRelaxed( AtomicTypes::Uint64 *atomicUint, Types::Uint64 value); // Atomically subtract from the specified 'atomicUint' the specified // 'value' and return the resulting value, without providing any memory // ordering guarantees. // *** atomic functions for pointer *** static void *getPtr(AtomicTypes::Pointer const *atomicPtr); // Atomically retrieve the value of the specified 'atomicPtr', // providing the sequential consistency memory ordering guarantee. static void *getPtrAcquire(AtomicTypes::Pointer const *atomicPtr); // Atomically retrieve the value of the specified 'atomicPtr', // providing the acquire memory ordering guarantee. static void *getPtrRelaxed(AtomicTypes::Pointer const *atomicPtr); // Atomically retrieve the value of the specified 'atomicPtr', without // providing any memory ordering guarantees. static void initPointer(AtomicTypes::Pointer *atomicPtr, void *initialValue = 0); // Initialize the specified 'atomicPtr' and set its value to the // optionally specified 'initialValue'. static void setPtr(AtomicTypes::Pointer *atomicPtr, void *value); // Atomically set the value of the specified 'atomicPtr' to the // specified 'value', providing the sequential consistency memory // ordering guarantee. static void setPtrRelaxed(AtomicTypes::Pointer *atomicPtr, void *value); // Atomically set the value of the specified 'atomicPtr' to the // specified 'value', without providing any memory ordering guarantees. static void setPtrRelease(AtomicTypes::Pointer *atomicPtr, void *value); // Atomically set the value of the specified 'atomicPtr' to the // specified 'value', providing the release memory ordering guarantee. static void *swapPtr(AtomicTypes::Pointer *atomicPtr, void *swapValue); // Atomically set the value of the specified 'atomicPtr' to the // specified 'swapValue', and return its previous value, providing the // sequential consistency memory ordering guarantee. static void *swapPtrAcqRel(AtomicTypes::Pointer *atomicPtr, void *swapValue); // Atomically set the value of the specified 'atomicPtr' to the // specified 'swapValue', and return its previous value, providing the // acquire/release memory ordering guarantee. static void *testAndSwapPtr(AtomicTypes::Pointer *atomicPtr, void *compareValue, void *swapValue); // Conditionally set the value of the specified 'atomicPtr' to the // specified 'swapValue' if and only if the value of 'atomicPtr' equals // the value of the specified 'compareValue', and return the initial // value of 'atomicPtr', providing the sequential consistency memory // ordering guarantee. The whole operation is performed atomically. static void *testAndSwapPtrAcqRel(AtomicTypes::Pointer *atomicPtr, void *compareValue, void *swapValue); // Conditionally set the value of the specified 'atomicPtr' to the // specified 'swapValue' if and only if the value of 'atomicPtr' equals // the value of the specified 'compareValue', and return the initial // value of 'atomicPtr', providing the acquire/release memory ordering // guarantee. The whole operation is performed atomically. }; // ============================================================================ // INLINE FUNCTION DEFINITIONS // ============================================================================ // ----------------------- // struct AtomicOperations // ----------------------- // *** atomic functions for int *** inline int AtomicOperations::getInt(AtomicTypes::Int const *atomicInt) { return Imp::getInt(atomicInt); } inline int AtomicOperations::getIntAcquire(AtomicTypes::Int const *atomicInt) { return Imp::getIntAcquire(atomicInt); } inline int AtomicOperations::getIntRelaxed(AtomicTypes::Int const *atomicInt) { return Imp::getIntRelaxed(atomicInt); } inline void AtomicOperations::initInt(AtomicTypes::Int *atomicInt, int initialValue) { Imp::initInt(atomicInt, initialValue); } inline void AtomicOperations::setInt(AtomicTypes::Int *atomicInt, int value) { Imp::setInt(atomicInt, value); } inline void AtomicOperations::setIntRelaxed(AtomicTypes::Int *atomicInt, int value) { Imp::setIntRelaxed(atomicInt, value); } inline void AtomicOperations::setIntRelease(AtomicTypes::Int *atomicInt, int value) { Imp::setIntRelease(atomicInt, value); } inline int AtomicOperations::swapInt(AtomicTypes::Int *atomicInt, int swapValue) { return Imp::swapInt(atomicInt, swapValue); } inline int AtomicOperations::swapIntAcqRel(AtomicTypes::Int *atomicInt, int swapValue) { return Imp::swapIntAcqRel(atomicInt, swapValue); } inline int AtomicOperations::testAndSwapInt(AtomicTypes::Int *atomicInt, int compareValue, int swapValue) { return Imp::testAndSwapInt(atomicInt, compareValue, swapValue); } inline int AtomicOperations::testAndSwapIntAcqRel(AtomicTypes::Int *atomicInt, int compareValue, int swapValue) { return Imp::testAndSwapIntAcqRel(atomicInt, compareValue, swapValue); } // *** atomic arithmetic functions for int *** inline void AtomicOperations::addInt(AtomicTypes::Int *atomicInt, int value) { Imp::addInt(atomicInt, value); } inline void AtomicOperations::addIntAcqRel(AtomicTypes::Int *atomicInt, int value) { Imp::addIntAcqRel(atomicInt, value); } inline void AtomicOperations::addIntRelaxed(AtomicTypes::Int *atomicInt, int value) { Imp::addIntRelaxed(atomicInt, value); } inline int AtomicOperations::addIntNv(AtomicTypes::Int *atomicInt, int value) { return Imp::addIntNv(atomicInt, value); } inline int AtomicOperations::addIntNvAcqRel(AtomicTypes::Int *atomicInt, int value) { return Imp::addIntNvAcqRel(atomicInt, value); } inline int AtomicOperations::addIntNvRelaxed(AtomicTypes::Int *atomicInt, int value) { return Imp::addIntNvRelaxed(atomicInt, value); } inline void AtomicOperations::decrementInt(AtomicTypes::Int *atomicInt) { Imp::decrementInt(atomicInt); } inline void AtomicOperations::decrementIntAcqRel(AtomicTypes::Int *atomicInt) { Imp::decrementIntAcqRel(atomicInt); } inline int AtomicOperations::decrementIntNv(AtomicTypes::Int *atomicInt) { return Imp::decrementIntNv(atomicInt); } inline int AtomicOperations::decrementIntNvAcqRel(AtomicTypes::Int *atomicInt) { return Imp::decrementIntNvAcqRel(atomicInt); } inline void AtomicOperations::incrementInt(AtomicTypes::Int *atomicInt) { Imp::incrementInt(atomicInt); } inline void AtomicOperations::incrementIntAcqRel(AtomicTypes::Int *atomicInt) { Imp::incrementIntAcqRel(atomicInt); } inline int AtomicOperations::incrementIntNv(AtomicTypes::Int *atomicInt) { return Imp::incrementIntNv(atomicInt); } inline int AtomicOperations::incrementIntNvAcqRel(AtomicTypes::Int *atomicInt) { return Imp::incrementIntNvAcqRel(atomicInt); } inline int AtomicOperations::subtractIntNv(AtomicTypes::Int *atomicInt, int value) { return Imp::subtractIntNv(atomicInt, value); } inline int AtomicOperations::subtractIntNvAcqRel(AtomicTypes::Int *atomicInt, int value) { return Imp::subtractIntNvAcqRel(atomicInt, value); } inline int AtomicOperations::subtractIntNvRelaxed(AtomicTypes::Int *atomicInt, int value) { return Imp::subtractIntNvRelaxed(atomicInt, value); } // *** atomic functions for Int64 *** inline Types::Int64 AtomicOperations::getInt64(AtomicTypes::Int64 const *atomicInt) { return Imp::getInt64(atomicInt); } inline Types::Int64 AtomicOperations::getInt64Acquire(AtomicTypes::Int64 const *atomicInt) { return Imp::getInt64Acquire(atomicInt); } inline Types::Int64 AtomicOperations::getInt64Relaxed(AtomicTypes::Int64 const *atomicInt) { return Imp::getInt64Relaxed(atomicInt); } inline void AtomicOperations::initInt64(AtomicTypes::Int64 *atomicInt, Types::Int64 initialValue) { Imp::initInt64(atomicInt, initialValue); } inline void AtomicOperations::setInt64(AtomicTypes::Int64 *atomicInt, Types::Int64 value) { Imp::setInt64(atomicInt, value); } inline void AtomicOperations::setInt64Relaxed(AtomicTypes::Int64 *atomicInt, Types::Int64 value) { Imp::setInt64Relaxed(atomicInt, value); } inline void AtomicOperations::setInt64Release(AtomicTypes::Int64 *atomicInt, Types::Int64 value) { Imp::setInt64Release(atomicInt, value); } inline Types::Int64 AtomicOperations::swapInt64(AtomicTypes::Int64 *atomicInt, Types::Int64 swapValue) { return Imp::swapInt64(atomicInt, swapValue); } inline Types::Int64 AtomicOperations::swapInt64AcqRel(AtomicTypes::Int64 *atomicInt, Types::Int64 swapValue) { return Imp::swapInt64AcqRel(atomicInt, swapValue); } inline Types::Int64 AtomicOperations::testAndSwapInt64( AtomicTypes::Int64 *atomicInt, Types::Int64 compareValue, Types::Int64 swapValue) { return Imp::testAndSwapInt64(atomicInt, compareValue, swapValue); } inline Types::Int64 AtomicOperations::testAndSwapInt64AcqRel( AtomicTypes::Int64 *atomicInt, Types::Int64 compareValue, Types::Int64 swapValue) { return Imp::testAndSwapInt64AcqRel(atomicInt, compareValue, swapValue); } // *** atomic arithmetic functions for Int64 *** inline void AtomicOperations::addInt64(AtomicTypes::Int64 *atomicInt, Types::Int64 value) { Imp::addInt64(atomicInt, value); } inline void AtomicOperations::addInt64AcqRel(AtomicTypes::Int64 *atomicInt, Types::Int64 value) { Imp::addInt64AcqRel(atomicInt, value); } inline void AtomicOperations::addInt64Relaxed(AtomicTypes::Int64 *atomicInt, Types::Int64 value) { Imp::addInt64Relaxed(atomicInt, value); } inline Types::Int64 AtomicOperations::addInt64Nv(AtomicTypes::Int64 *atomicInt, Types::Int64 value) { return Imp::addInt64Nv(atomicInt, value); } inline Types::Int64 AtomicOperations::addInt64NvAcqRel(AtomicTypes::Int64 *atomicInt, Types::Int64 value) { return Imp::addInt64NvAcqRel(atomicInt, value); } inline Types::Int64 AtomicOperations::addInt64NvRelaxed(AtomicTypes::Int64 *atomicInt, Types::Int64 value) { return Imp::addInt64NvRelaxed(atomicInt, value); } inline void AtomicOperations::decrementInt64(AtomicTypes::Int64 *atomicInt) { Imp::decrementInt64(atomicInt); } inline void AtomicOperations::decrementInt64AcqRel(AtomicTypes::Int64 *atomicInt) { Imp::decrementInt64AcqRel(atomicInt); } inline Types::Int64 AtomicOperations::decrementInt64Nv(AtomicTypes::Int64 *atomicInt) { return Imp::decrementInt64Nv(atomicInt); } inline Types::Int64 AtomicOperations::decrementInt64NvAcqRel(AtomicTypes::Int64 *atomicInt) { return Imp::decrementInt64NvAcqRel(atomicInt); } inline void AtomicOperations::incrementInt64(AtomicTypes::Int64 *atomicInt) { Imp::incrementInt64(atomicInt); } inline void AtomicOperations::incrementInt64AcqRel(AtomicTypes::Int64 *atomicInt) { Imp::incrementInt64AcqRel(atomicInt); } inline Types::Int64 AtomicOperations::incrementInt64Nv(AtomicTypes::Int64 *atomicInt) { return Imp::incrementInt64Nv(atomicInt); } inline Types::Int64 AtomicOperations::incrementInt64NvAcqRel(AtomicTypes::Int64 *atomicInt) { return Imp::incrementInt64NvAcqRel(atomicInt); } inline Types::Int64 AtomicOperations::subtractInt64Nv(AtomicTypes::Int64 *atomicInt, Types::Int64 value) { return Imp::subtractInt64Nv(atomicInt, value); } inline Types::Int64 AtomicOperations::subtractInt64NvAcqRel( AtomicTypes::Int64 *atomicInt, Types::Int64 value) { return Imp::subtractInt64NvAcqRel(atomicInt, value); } inline Types::Int64 AtomicOperations::subtractInt64NvRelaxed( AtomicTypes::Int64 *atomicInt, Types::Int64 value) { return Imp::subtractInt64NvRelaxed(atomicInt, value); } // *** atomic functions for unsigned int *** inline unsigned int AtomicOperations::getUint(AtomicTypes::Uint const *atomicUint) { return Imp::getUint(atomicUint); } inline unsigned int AtomicOperations::getUintAcquire( AtomicTypes::Uint const *atomicUint) { return Imp::getUintAcquire(atomicUint); } inline unsigned int AtomicOperations::getUintRelaxed( AtomicTypes::Uint const *atomicUint) { return Imp::getUintRelaxed(atomicUint); } inline void AtomicOperations::initUint(AtomicTypes::Uint *atomicUint, unsigned int initialValue) { Imp::initUint(atomicUint, initialValue); } inline void AtomicOperations::setUint(AtomicTypes::Uint *atomicUint, unsigned int value) { Imp::setUint(atomicUint, value); } inline void AtomicOperations::setUintRelaxed(AtomicTypes::Uint *atomicUint, unsigned int value) { Imp::setUintRelaxed(atomicUint, value); } inline void AtomicOperations::setUintRelease(AtomicTypes::Uint *atomicUint, unsigned int value) { Imp::setUintRelease(atomicUint, value); } inline unsigned int AtomicOperations::swapUint(AtomicTypes::Uint *atomicUint, unsigned int swapValue) { return Imp::swapUint(atomicUint, swapValue); } inline unsigned int AtomicOperations::swapUintAcqRel(AtomicTypes::Uint *atomicUint, unsigned int swapValue) { return Imp::swapUintAcqRel(atomicUint, swapValue); } inline unsigned int AtomicOperations::testAndSwapUint(AtomicTypes::Uint *atomicUint, unsigned int compareValue, unsigned int swapValue) { return Imp::testAndSwapUint(atomicUint, compareValue, swapValue); } inline unsigned int AtomicOperations::testAndSwapUintAcqRel( AtomicTypes::Uint *atomicUint, unsigned int compareValue, unsigned int swapValue) { return Imp::testAndSwapUintAcqRel(atomicUint, compareValue, swapValue); } // *** atomic arithmetic functions for unsigned int *** inline void AtomicOperations::addUint(AtomicTypes::Uint *atomicUint, unsigned int value) { Imp::addUint(atomicUint, value); } inline void AtomicOperations::addUintAcqRel(AtomicTypes::Uint *atomicUint, unsigned int value) { Imp::addUintAcqRel(atomicUint, value); } inline void AtomicOperations::addUintRelaxed(AtomicTypes::Uint *atomicUint, unsigned int value) { Imp::addUintRelaxed(atomicUint, value); } inline unsigned int AtomicOperations::addUintNv(AtomicTypes::Uint *atomicUint, unsigned int value) { return Imp::addUintNv(atomicUint, value); } inline unsigned int AtomicOperations::addUintNvAcqRel(AtomicTypes::Uint *atomicUint, unsigned int value) { return Imp::addUintNvAcqRel(atomicUint, value); } inline unsigned int AtomicOperations::addUintNvRelaxed(AtomicTypes::Uint *atomicUint, unsigned int value) { return Imp::addUintNvRelaxed(atomicUint, value); } inline void AtomicOperations::decrementUint(AtomicTypes::Uint *atomicUint) { Imp::decrementUint(atomicUint); } inline void AtomicOperations::decrementUintAcqRel(AtomicTypes::Uint *atomicUint) { Imp::decrementUintAcqRel(atomicUint); } inline unsigned int AtomicOperations::decrementUintNv(AtomicTypes::Uint *atomicUint) { return Imp::decrementUintNv(atomicUint); } inline unsigned int AtomicOperations::decrementUintNvAcqRel( AtomicTypes::Uint *atomicUint) { return Imp::decrementUintNvAcqRel(atomicUint); } inline void AtomicOperations::incrementUint(AtomicTypes::Uint *atomicUint) { Imp::incrementUint(atomicUint); } inline void AtomicOperations::incrementUintAcqRel(AtomicTypes::Uint *atomicUint) { Imp::incrementUintAcqRel(atomicUint); } inline unsigned int AtomicOperations::incrementUintNv(AtomicTypes::Uint *atomicUint) { return Imp::incrementUintNv(atomicUint); } inline unsigned int AtomicOperations::incrementUintNvAcqRel( AtomicTypes::Uint *atomicUint) { return Imp::incrementUintNvAcqRel(atomicUint); } inline unsigned int AtomicOperations::subtractUintNv(AtomicTypes::Uint *atomicUint, unsigned int value) { return Imp::subtractUintNv(atomicUint, value); } inline unsigned int AtomicOperations::subtractUintNvAcqRel( AtomicTypes::Uint *atomicUint, unsigned int value) { return Imp::subtractUintNvAcqRel(atomicUint, value); } inline unsigned int AtomicOperations::subtractUintNvRelaxed( AtomicTypes::Uint *atomicUint, unsigned int value) { return Imp::subtractUintNvRelaxed(atomicUint, value); } // *** atomic functions for Uint64 *** inline Types::Uint64 AtomicOperations::getUint64(AtomicTypes::Uint64 const *atomicUint) { return Imp::getUint64(atomicUint); } inline Types::Uint64 AtomicOperations::getUint64Acquire(AtomicTypes::Uint64 const *atomicUint) { return Imp::getUint64Acquire(atomicUint); } inline Types::Uint64 AtomicOperations::getUint64Relaxed(AtomicTypes::Uint64 const *atomicUint) { return Imp::getUint64Relaxed(atomicUint); } inline void AtomicOperations::initUint64(AtomicTypes::Uint64 *atomicUint, Types::Uint64 initialValue) { Imp::initUint64(atomicUint, initialValue); } inline void AtomicOperations::setUint64(AtomicTypes::Uint64 *atomicUint, Types::Uint64 value) { Imp::setUint64(atomicUint, value); } inline void AtomicOperations::setUint64Relaxed(AtomicTypes::Uint64 *atomicUint, Types::Uint64 value) { Imp::setUint64Relaxed(atomicUint, value); } inline void AtomicOperations::setUint64Release(AtomicTypes::Uint64 *atomicUint, Types::Uint64 value) { Imp::setUint64Release(atomicUint, value); } inline Types::Uint64 AtomicOperations::swapUint64(AtomicTypes::Uint64 *atomicUint, Types::Uint64 swapValue) { return Imp::swapUint64(atomicUint, swapValue); } inline Types::Uint64 AtomicOperations::swapUint64AcqRel( AtomicTypes::Uint64 *atomicUint, Types::Uint64 swapValue) { return Imp::swapUint64AcqRel(atomicUint, swapValue); } inline Types::Uint64 AtomicOperations::testAndSwapUint64( AtomicTypes::Uint64 *atomicUint, Types::Uint64 compareValue, Types::Uint64 swapValue) { return Imp::testAndSwapUint64(atomicUint, compareValue, swapValue); } inline Types::Uint64 AtomicOperations::testAndSwapUint64AcqRel( AtomicTypes::Uint64 *atomicUint, Types::Uint64 compareValue, Types::Uint64 swapValue) { return Imp::testAndSwapUint64AcqRel(atomicUint, compareValue, swapValue); } // *** atomic arithmetic functions for Uint64 *** inline void AtomicOperations::addUint64(AtomicTypes::Uint64 *atomicUint, Types::Uint64 value) { Imp::addUint64(atomicUint, value); } inline void AtomicOperations::addUint64AcqRel(AtomicTypes::Uint64 *atomicUint, Types::Uint64 value) { Imp::addUint64AcqRel(atomicUint, value); } inline void AtomicOperations::addUint64Relaxed(AtomicTypes::Uint64 *atomicUint, Types::Uint64 value) { Imp::addUint64Relaxed(atomicUint, value); } inline Types::Uint64 AtomicOperations::addUint64Nv(AtomicTypes::Uint64 *atomicUint, Types::Uint64 value) { return Imp::addUint64Nv(atomicUint, value); } inline Types::Uint64 AtomicOperations::addUint64NvAcqRel( AtomicTypes::Uint64 *atomicUint, Types::Uint64 value) { return Imp::addUint64NvAcqRel(atomicUint, value); } inline Types::Uint64 AtomicOperations::addUint64NvRelaxed( AtomicTypes::Uint64 *atomicUint, Types::Uint64 value) { return Imp::addUint64NvRelaxed(atomicUint, value); } inline void AtomicOperations::decrementUint64(AtomicTypes::Uint64 *atomicUint) { Imp::decrementUint64(atomicUint); } inline void AtomicOperations::decrementUint64AcqRel(AtomicTypes::Uint64 *atomicUint) { Imp::decrementUint64AcqRel(atomicUint); } inline Types::Uint64 AtomicOperations::decrementUint64Nv(AtomicTypes::Uint64 *atomicUint) { return Imp::decrementUint64Nv(atomicUint); } inline Types::Uint64 AtomicOperations::decrementUint64NvAcqRel(AtomicTypes::Uint64 *atomicUint) { return Imp::decrementUint64NvAcqRel(atomicUint); } inline void AtomicOperations::incrementUint64(AtomicTypes::Uint64 *atomicUint) { Imp::incrementUint64(atomicUint); } inline void AtomicOperations::incrementUint64AcqRel(AtomicTypes::Uint64 *atomicUint) { Imp::incrementUint64AcqRel(atomicUint); } inline Types::Uint64 AtomicOperations::incrementUint64Nv(AtomicTypes::Uint64 *atomicUint) { return Imp::incrementUint64Nv(atomicUint); } inline Types::Uint64 AtomicOperations::incrementUint64NvAcqRel(AtomicTypes::Uint64 *atomicUint) { return Imp::incrementUint64NvAcqRel(atomicUint); } inline Types::Uint64 AtomicOperations::subtractUint64Nv( AtomicTypes::Uint64 *atomicUint, Types::Uint64 value) { return Imp::subtractUint64Nv(atomicUint, value); } inline Types::Uint64 AtomicOperations::subtractUint64NvAcqRel( AtomicTypes::Uint64 *atomicUint, Types::Uint64 value) { return Imp::subtractUint64NvAcqRel(atomicUint, value); } inline Types::Uint64 AtomicOperations::subtractUint64NvRelaxed( AtomicTypes::Uint64 *atomicUint, Types::Uint64 value) { return Imp::subtractUint64NvRelaxed(atomicUint, value); } // *** atomic functions for pointer *** inline void *AtomicOperations::getPtr(AtomicTypes::Pointer const *atomicPtr) { return Imp::getPtr(atomicPtr); } inline void * AtomicOperations::getPtrAcquire(AtomicTypes::Pointer const *atomicPtr) { return Imp::getPtrAcquire(atomicPtr); } inline void * AtomicOperations::getPtrRelaxed(AtomicTypes::Pointer const *atomicPtr) { return Imp::getPtrRelaxed(atomicPtr); } inline void AtomicOperations::initPointer(AtomicTypes::Pointer *atomicPtr, void *initialValue) { Imp::initPointer(atomicPtr, initialValue); } inline void AtomicOperations::setPtr(AtomicTypes::Pointer *atomicPtr, void *value) { Imp::setPtr(atomicPtr, value); } inline void AtomicOperations::setPtrRelaxed(AtomicTypes::Pointer *atomicPtr, void *value) { Imp::setPtrRelaxed(atomicPtr, value); } inline void AtomicOperations::setPtrRelease(AtomicTypes::Pointer *atomicPtr, void *value) { Imp::setPtrRelease(atomicPtr, value); } inline void *AtomicOperations::swapPtr(AtomicTypes::Pointer *atomicPtr, void *swapValue) { return Imp::swapPtr(atomicPtr, swapValue); } inline void *AtomicOperations::swapPtrAcqRel(AtomicTypes::Pointer *atomicPtr, void *swapValue) { return Imp::swapPtrAcqRel(atomicPtr, swapValue); } inline void *AtomicOperations::testAndSwapPtr(AtomicTypes::Pointer *atomicPtr, void *compareValue, void *swapValue) { return Imp::testAndSwapPtr(atomicPtr, compareValue, swapValue); } inline void *AtomicOperations::testAndSwapPtrAcqRel( AtomicTypes::Pointer *atomicPtr, void *compareValue, void *swapValue) { return Imp::testAndSwapPtrAcqRel(atomicPtr, compareValue, swapValue); } } // close package namespace } // close enterprise namespace #endif // ---------------------------------------------------------------------------- // Copyright 2013 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ----------------------------- END-OF-FILE ----------------------------------