// bsls_atomicoperations_default.h                                    -*-C++-*-
#ifndef INCLUDED_BSLS_ATOMICOPERATIONS_DEFAULT
#define INCLUDED_BSLS_ATOMICOPERATIONS_DEFAULT

#include <bsls_ident.h>
BSLS_IDENT("$Id: $")

//@PURPOSE: Provide default implementation for atomic operations.
//
//@CLASSES:
//  bsls::AtomicOperations_DefaultInt: defaults for atomic operations on int
//  bsls::AtomicOperations_DefaultInt64: defaults for Int64
//  bsls::AtomicOperations_DefaultPointer32: defaults for 32-bit pointer
//  bsls::AtomicOperations_DefaultPointer64: defaults for 64-bit pointer
//  bsls::AtomicOperations_Default32: all atomics for a generic 32-bit platform
//  bsls::AtomicOperations_Default64: all atomics for a generic 64-bit platform
//
//@DESCRIPTION: [**PRIVATE**] This component provides classes having default
// implementations of atomic operations independent of a any specific platform.
// The purpose of these classes is for them to be combined with
// platform-specific implementations of atomic operations to form a full set of
// atomic operations.
//
// [**WARNING**] This component should not be used directly by client code.  It
// is subject to change without warning.
//
// The implementation of atomic operations splits the set of operations into
// two groups: essential (core) operations and non-essential operations.  The
// essential core operations, such as `getInt`, `setInt`, `swapInt`,
// `testAndSwapInt`, must be implemented on every target platform.  The
// non-essential operations, such as `incrementInt`, `decrementInt`, have
// default implementations written in terms of the core operations (though the
// default implementation may be overridden for a target platform).
//
// This component provides the default implementations for non-essential atomic
// operations.  For the essential core operations, it provides only function
// prototypes without any concrete implementation.  The concrete implementation
// for core operations on each platform are provided by a platform-specific
// implementation component.
//
///Design of Components Providing Atomic Operations
///------------------------------------------------
// There are about 70 different atomic operations we provide in this atomics
// library.  Only a fraction of these operations (about 10-15) have
// implementations specific to a target platform.  These are the core atomic
// operations.  Other operations have implementations that are independent of
// the platform, and are defined in terms of those core operations.
//
// A primary design objective for this implementation of atomic operations is
// to provide a single common implementation for the platform-independent,
// non-essential, atomic operations.  This way, each platform-specific
// implementation of atomics needs to provide only the 10-15 core operations,
// and may obtain the remaining 60 atomic operations automatically from this
// default implementation component.
//
// The implementation technique used to achieve this goal is called the
// Curiously Recurring Template Pattern, or CRTP.
//
// In the CRTP a derived class inherits from the base class, but the base class
// is parameterized with the derived class template parameter.  In the context
// of atomic operations, the CRTP allows the non-essential base class methods
// to be accessed through the platform specific derived class, while the
// template parameterization of the base class allows the implementations for
// platform-independent (non-essential) operations in the base class to be
// implemented in terms of the core operations implemented in the
// platform-specific derived class.
//
// Let's illustrate this idea with an example.  The base class, `AtomicsBase`,
// will provide an implementation for a single non-essential atomic operation,
// `getIntAcquire`, whose implementation delegates to the platform-specific
// implementation of another, (core) atomic operation, `getInt`:
// ```
// template <class IMP>
// struct AtomicsBase<IMP>
// {
//     // static
//     // int getInt(int volatile *);
//     //   Implemented in the derived class, 'IMP'.
//
//     static
//     int getIntAcquire(int volatile *obj)
//         // Platform-independent; implemented in terms of the derived
//         // 'getInt'.
//     {
//         return IMP::getInt(obj);
//     }
// };
// ```
// Now we define a platform-specific implementation of the atomics class for
// the x86 platform providing the core operation `getInt`:
// ```
// struct AtomicsX86 : AtomicsBase<AtomicsX86>
// {
//     static
//     int getInt(int volatile *obj)
//         // Platform-specific implementation.
//     {
//         // ...whatever is necessary for this atomic operation on x86
//     }
// };
// ```
// To get an idea what the effective interface and the implementation of the
// `AtomicsX86` class looks like, we can flatten the hierarchy of `AtomicsX86`
// and remove the `AtomicsBase` class from the picture, as if we implemented
// `AtomicsX86` without the help of `AtomicsBase`.  The effective interface and
// the implementation of `AtomicsX86` is as follows:
// ```
// struct AtomicsX86Flattened
// {
//     static
//     int getInt(int volatile *obj)
//         // Platform-specific implementation.
//     {
//         // ...whatever is necessary for this atomic operation on x86
//     }
//
//     static
//     int getIntAcquire(int volatile *obj)
//         // Platform-independent; implemented in terms of 'getInt'.
//     {
//         return getInt(obj);
//     }
// };
// ```
// The above code shows that the design goal is achieved: Platform-independent
// atomic operations are factored out into easily reusable `AtomicsBase` which,
// when combined with platform-specific atomic operations, produces the
// complete set of atomic operations for a given target-platform.
//
///Component and Class Hierarchy for Atomic Operations
///---------------------------------------------------
// This section describes the hierarchy of components and types that implement
// atomic operations.  Below is the list of base classes providing default
// implementations of platform-independent, non-essential atomic operations.
// Atomic operations for different data types are factored into their own base
// classes:
// * bsls::AtomicOperations_DefaultInt - provides atomic operations for int
// * bsls::AtomicOperations_DefaultInt64 - for Int64
// * bsls::AtomicOperations_DefaultPointer32 - for 32-bit pointer
// * bsls::AtomicOperations_DefaultPointer64 - for 64-bit pointer
//
// The platform-specific core atomic operations are left unimplemented in these
// default implementation classes.  The implementations for those operations
// have to be provided by a platform-specific derived classes.
//
// The above default implementation classes are combined (using inheritance)
// into more specialized base classes that provide nearly complete set of
// atomic operations for a generic platform:
//
// * bsls::AtomicOperations_Default32 - a set of atomic operations for a
//   generic 32-bit platform
// * bsls::AtomicOperations_Default64 - a set of atomic operations for a
//   generic 64-bit platform
//
// This is how the generic platform base classes are composed:
// * bsls::AtomicOperations_Default32 : AtomicOperations_DefaultInt,
//   AtomicOperations_DefaultInt64, AtomicOperations_DefaultPointer32
// * bsls::AtomicOperations_Default64 : AtomicOperations_DefaultInt,
//   AtomicOperations_DefaultInt64, AtomicOperations_DefaultPointer64
//
// A typical derived class implementing platform-specific atomic operations
// needs to derive from either `bsls::AtomicOperations_Default32` (if the
// platform is 32-bit) or `bsls::AtomicOperations_Default64` (if the platform
// is 64-bit).
//
// For example, let's take the X86_64 platform with GCC compiler.  The derived
// class for this platform, `bsls::AtomicOperations_X64_ALL_GCC`, inherits from
// `bsls::AtomicOperations_Default64` and implements all platform-specific
// atomic operations:
// ```
// struct bsls::AtomicOperations_X64_ALL_GCC
//     : bsls::AtomicOperations_Default64<bsls::AtomicOperations_X64_ALL_GCC>
// {
//     typedef bsls::Atomic_TypeTraits<bsls::AtomicOperations_X64_ALL_GCC>
//         AtomicTypes;   // for explanation of atomic type traits see below
//
//         // *** atomic functions for int ***
//     static int getInt(const AtomicTypes::Int *atomicInt);
//     static void setInt(AtomicTypes::Int *atomicInt, int value);
//     // ...
//
//         // *** atomic functions for Int64 ***
//     static bsls::Types::Int64 getInt64(
//                 AtomicTypes::Int64 const *atomicInt);
//     static void setInt64(
//                 AtomicTypes::Int64 *atomicInt, bsls::Types::Int64 value);
//     // ...
// };
// ```
// A derived class can also override some default atomic implementations from a
// base class.  For example, `bsls::AtomicOperations_X64_ALL_GCC` can provide a
// better implementation for `getIntAcquire` than the one provided by the
// `bsls::AtomicOperations_DefaultInt` base class.  So
// `bsls::AtomicOperations_X64_ALL_GCC` implements its own `getIntAcquire` with
// the same signature as in the base class:
// ```
// struct bsls::AtomicOperations_X64_ALL_GCC
//     : bsls::AtomicOperations_Default64<bsls::AtomicOperations_X64_ALL_GCC>
// {
//         // *** atomic functions for int ***
//     static int getIntAcquire(const AtomicTypes::Int *atomicInt);
//     // ...
// };
// ```
// Technically speaking, this is not overriding, but hiding the respective
// methods of the base class, but for our purpose, it works as if the methods
// were overridden.
//
// Platform-specific atomic operations for other platforms are implemented in a
// similar manner.  Here is a conceptual diagram of relationships between
// classes that provide the default atomic operations and platform-specific
// atomic operations (the bsls::AtomicOperations_ prefix is omitted for
// brevity):
// ```
// DefaultPointer32      DefaultInt         DefaultInt64    DefaultPointer64
//         ^                  ^                   ^                 ^
//         |                  |                   |                 |
//         +---------------+  +-------------------+  +--------------+
//                         |  |                   |  |
//                       Default32              Default64
//                           ^                      ^
//                           |                      |
//             X86_ALL_GCC --+                      +-- X64_ALL_GCC
//                           |                      |
//            X86_WIN_MSVC --+                      +-- X64_WIN_MSVC
//                           |                      |
//       POWERPC32_AIX_XLC --+                      +-- POWERPC64_AIX_XLC
//                           |                      |
//          SPARC32_SUN_CC --+                      +-- SPARC64_SUN_CC
//                                                  |
//                                                  +-- IA64_HP_ACC
// ```
//
// The last part of the implementation is the atomic type traits class.  We
// need a special representation for atomic primitive types to ensure
// conformance to size and alignment requirements for each platform.  For
// example, the atomic primitive type for `int` is usually a 4-byte aligned
// `volatile int`.  Since the alignment is specified differently for different
// platforms and compilers, the atomic type traits class allows us to abstract
// the rest of the implementation of atomics from those differences.
//
// This default implementation component provides only a declaration of a
// generic atomic type traits class:
// ```
// template <class IMP>
// struct bsls::Atomic_TypeTraits;
// ```
// Each platform-specific implementation has to provide its own specialization
// of the type traits class.  For example, the specialization for the x86_64
// platform defined by the `bsls::AtomicOperations_X64_ALL_GCC` class might
// look like:
// ```
// template <>
// struct bsls::Atomic_TypeTraits<bsls::AtomicOperations_X64_ALL_GCC>
// {
//     struct Int
//     {
//         volatile int d_value __attribute__((__aligned__(sizeof(int))));
//     };
//
//     struct Int64
//     {
//         volatile bsls::Types::Int64 d_value
//                   __attribute__((__aligned__(sizeof(bsls::Types::Int64))));
//     };
//
//     struct Pointer
//     {
//         void * volatile d_value
//                               __attribute__((__aligned__(sizeof(void *))));
//     };
// };
// ```
//
///Usage
///-----
// This component is a private implementation type of `bsls_atomicoperations`;
// see `bsls_atomicoperations` for a usage example.

#include <bsls_types.h>

namespace BloombergLP {

namespace bsls {

                     // ==================================
                     // struct AtomicOperations_DefaultInt
                     // ==================================

template <class IMP>
struct Atomic_TypeTraits;

/// This class provides default implementations of non-essential atomic
/// operations for the 32-bit integer type independent on any specific
/// platform.  It also provides prototypes for the atomic operations for the
/// 32-bit integer type that have to be implemented separately for each
/// specific platform.  These platform-independent and platform-specific
/// atomic operations together form a full set of atomic operations for the
/// 32-bit integer type.
template <class IMP>
struct AtomicOperations_DefaultInt
{
  public:
    // PUBLIC TYPES
    typedef Atomic_TypeTraits<IMP> AtomicTypes;

  private:
    // The following are signatures for the core atomics interface, the
    // implementation of which must be provided by a derived platform-specific
    // 'IMP' class.

    // NOT IMPLEMENTED

    /// Atomically add to the specified `atomicInt` the specified `value`
    /// and return the resulting value, providing the sequential consistency
    /// memory ordering guarantee.
    static int addIntNv(typename AtomicTypes::Int *atomicInt, int value);

    /// Atomically retrieve the value of the specified `atomicInt`,
    /// providing the sequential consistency memory ordering guarantee.
    static int getInt(typename AtomicTypes::Int const *atomicInt);

    /// Atomically set the value of the specified `atomicInt` to the
    /// specified `value`, providing the sequential consistency memory
    /// ordering guarantee.
    static void setInt(typename AtomicTypes::Int *atomicInt, int value);

    /// 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 swapInt(typename AtomicTypes::Int *atomicInt, 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 testAndSwapInt(typename AtomicTypes::Int *atomicInt,
                              int                        compareValue,
                              int                        swapValue);

  public:
    // CLASS METHODS

    /// Atomically retrieve the value of the specified `atomicInt`,
    /// providing the acquire memory ordering guarantee.
    static int getIntAcquire(typename AtomicTypes::Int const *atomicInt);

    /// Atomically retrieve the value of the specified `atomicInt`, without
    /// providing any memory ordering guarantees.
    static int getIntRelaxed(typename AtomicTypes::Int const *atomicInt);

    /// Initialize the specified `atomicInt` and set its value to the
    /// optionally specified `initialValue`.
    static void initInt(typename AtomicTypes::Int *atomicInt,
                        int                        initialValue = 0);

    /// Atomically set the value of the specified `atomicInt` to the
    /// specified `value`, without providing any memory ordering guarantees.
    static void setIntRelaxed(typename AtomicTypes::Int *atomicInt, int value);

    /// Atomically set the value of the specified `atomicInt` to the
    /// specified `value`, providing the release memory ordering guarantee.
    static void setIntRelease(typename AtomicTypes::Int *atomicInt, int value);

    /// 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 swapIntAcqRel(typename AtomicTypes::Int *atomicInt,
                             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 int testAndSwapIntAcqRel(typename AtomicTypes::Int *atomicInt,
                                    int                        compareValue,
                                    int                        swapValue);

    // Arithmetic

    /// Atomically add to the specified `atomicInt` the specified `value`,
    /// providing the sequential consistency memory ordering guarantee.
    static void addInt(typename AtomicTypes::Int *atomicInt, int value);

    /// Atomically add to the specified `atomicInt` the specified `value`,
    /// providing the acquire/release memory ordering guarantee.
    static void addIntAcqRel(typename AtomicTypes::Int *atomicInt, int value);

    /// Atomically add to the specified `atomicInt` the specified `value`,
    /// without providing any memory ordering guarantees.
    static void addIntRelaxed(typename 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 addIntNvAcqRel(typename 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 int addIntNvRelaxed(typename AtomicTypes::Int *atomicInt,
                               int                        value);

    /// Atomically decrement the value of the specified `atomicInt` by 1,
    /// providing the sequential consistency memory ordering guarantee.
    static void decrementInt(typename AtomicTypes::Int *atomicInt);

    /// Atomically decrement the value of the specified `atomicInt` by 1,
    /// providing the acquire/release memory ordering guarantee.
    static void decrementIntAcqRel(typename AtomicTypes::Int *atomicInt);

    /// Atomically decrement the specified `atomicInt` by 1 and return the
    /// resulting value, providing the sequential consistency memory
    /// ordering guarantee.
    static int decrementIntNv(typename AtomicTypes::Int *atomicInt);

    /// Atomically decrement the specified `atomicInt` by 1 and return the
    /// resulting value, providing the acquire/release memory ordering
    /// guarantee.
    static int decrementIntNvAcqRel(typename AtomicTypes::Int *atomicInt);

    /// Atomically increment the value of the specified `atomicInt` by 1,
    /// providing the sequential consistency memory ordering guarantee.
    static void incrementInt(typename AtomicTypes::Int *atomicInt);

    /// Atomically increment the value of the specified `atomicInt` by 1,
    /// providing the acquire/release memory ordering guarantee.
    static void incrementIntAcqRel(typename AtomicTypes::Int *atomicInt);

    /// Atomically increment the specified `atomicInt` by 1 and return the
    /// resulting value, providing the sequential consistency memory
    /// ordering guarantee.
    static int incrementIntNv(typename AtomicTypes::Int *atomicInt);

    /// Atomically increment the specified `atomicInt` by 1 and return the
    /// resulting value, providing the acquire/release memory ordering
    /// guarantee.
    static int incrementIntNvAcqRel(typename AtomicTypes::Int *atomicInt);

    /// Atomically subtract from the specified `atomicInt` the specified
    /// `value` and return the resulting value, providing the sequential
    /// consistency memory ordering guarantee.
    static int subtractIntNv(typename 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 subtractIntNvAcqRel(typename 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.
    static int subtractIntNvRelaxed(typename AtomicTypes::Int *atomicInt,
                                    int                        value);
};

                    // ====================================
                    // struct AtomicOperations_DefaultInt64
                    // ====================================

/// This class provides default implementations of non-essential atomic
/// operations for the 64-bit integer type independent on any specific
/// platform.  It also provides prototypes for the atomic operations for the
/// 64-bit integer type that have to be implemented separately for each
/// specific platform.  These platform-independent and platform-specific
/// atomic operations together form a full set of atomic operations for the
/// 64-bit integer type.
template <class IMP>
struct AtomicOperations_DefaultInt64
{
  public:
    // PUBLIC TYPES
    typedef Atomic_TypeTraits<IMP> AtomicTypes;

  private:
    // The following are signatures for the core atomics interface, the
    // implementation of which must be provided by a derived platform-specific
    // 'IMP' class.

    // NOT IMPLEMENTED

    /// Atomically add to the specified `atomicInt` the specified `value`
    /// and return the resulting value, providing the sequential consistency
    /// memory ordering guarantee.
    static Types::Int64 addInt64Nv(typename AtomicTypes::Int64 *atomicInt,
                                   Types::Int64                 value);

    /// Atomically retrieve the value of the specified `atomicInt`,
    /// providing the sequential consistency memory ordering guarantee.
    static Types::Int64 getInt64(typename AtomicTypes::Int64 const *atomicInt);

    /// Atomically set the value of the specified `atomicInt` to the
    /// specified `value`, providing the sequential consistency memory
    /// ordering guarantee.
    static void setInt64(typename AtomicTypes::Int64 *atomicInt,
                         Types::Int64                 value);

    /// 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 swapInt64(typename AtomicTypes::Int64 *atomicInt,
                                  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 testAndSwapInt64(
                                     typename AtomicTypes::Int64 *atomicInt,
                                     Types::Int64                 compareValue,
                                     Types::Int64                 swapValue);

  public:
    // CLASS METHODS

    /// Atomically retrieve the value of the specified `atomicInt`,
    /// providing the acquire memory ordering guarantee.
    static Types::Int64 getInt64Acquire(
                                 typename AtomicTypes::Int64 const *atomicInt);

    /// Atomically retrieve the value of the specified `atomicInt`, without
    /// providing any memory ordering guarantees.
    static Types::Int64 getInt64Relaxed(
                                 typename AtomicTypes::Int64 const *atomicInt);

    /// Initialize the specified `atomicInt` and set its value to the
    /// optionally specified `initialValue`.
    static void initInt64(typename AtomicTypes::Int64 *atomicInt,
                          Types::Int64                 initialValue = 0);

    /// Atomically set the value of the specified `atomicInt` to the
    /// specified `value`, without providing any memory ordering guarantees.
    static void setInt64Relaxed(typename 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 void setInt64Release(typename AtomicTypes::Int64 *atomicInt,
                                Types::Int64                 value);

    /// 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 swapInt64AcqRel(
                                       typename AtomicTypes::Int64 *atomicInt,
                                       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(
                                     typename AtomicTypes::Int64 *atomicInt,
                                     Types::Int64                 compareValue,
                                     Types::Int64                 swapValue);

    // Arithmetic

    /// Atomically add to the specified `atomicInt` the specified `value`,
    /// providing the sequential consistency memory ordering guarantee.
    static void addInt64(typename AtomicTypes::Int64 *atomicInt,
                         Types::Int64                 value);

    /// Atomically add to the specified `atomicInt` the specified `value`,
    /// providing the acquire/release memory ordering guarantee.
    static void addInt64AcqRel(typename AtomicTypes::Int64 *atomicInt,
                               Types::Int64                 value);

    /// Atomically add to the specified `atomicInt` the specified `value`,
    /// without providing any memory ordering guarantees.
    static void addInt64Relaxed(typename 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 addInt64NvAcqRel(
                                        typename 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 Types::Int64 addInt64NvRelaxed(
                                        typename AtomicTypes::Int64 *atomicInt,
                                        Types::Int64                 value);

    /// Atomically decrement the specified `atomicInt` by 1, providing the
    /// sequential consistency memory ordering guarantee.
    static void decrementInt64(typename AtomicTypes::Int64 *atomicInt);

    /// Atomically decrement the specified `atomicInt` by 1, providing the
    /// acquire/release memory ordering guarantee.
    static void decrementInt64AcqRel(typename 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 decrementInt64Nv(
                                       typename AtomicTypes::Int64 *atomicInt);

    /// Atomically decrement the specified `atomicInt` by 1 and return the
    /// resulting value, providing the acquire/release memory ordering
    /// guarantee.
    static Types::Int64 decrementInt64NvAcqRel(
                                       typename AtomicTypes::Int64 *atomicInt);

    /// Atomically increment the value of the specified `atomicInt` by 1,
    /// providing the sequential consistency memory ordering guarantee.
    static void incrementInt64(typename AtomicTypes::Int64 *atomicInt);

    /// Atomically increment the value of the specified `atomicInt` by 1,
    /// providing the acquire/release memory ordering guarantee.
    static void incrementInt64AcqRel(typename 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 incrementInt64Nv(
                                       typename 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 incrementInt64NvAcqRel(
                                       typename AtomicTypes::Int64 *atomicInt);

    /// Atomically subtract from the specified `atomicInt` the specified
    /// `value` and return the resulting value, providing the sequential
    /// consistency memory ordering guarantee.
    static Types::Int64 subtractInt64Nv(typename 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 subtractInt64NvAcqRel(
                                        typename 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.
    static Types::Int64 subtractInt64NvRelaxed(
                                        typename AtomicTypes::Int64 *atomicInt,
                                        Types::Int64                 value);
};

                    // ===================================
                    // struct AtomicOperations_DefaultUint
                    // ===================================

template <class IMP>
struct Atomic_TypeTraits;

/// This class provides default implementations of non-essential atomic
/// operations for the 32-bit unsigned integer type independent on any
/// specific platform.  It also provides prototypes for the atomic
/// operations for the 32-bit unsigned integer type that have to be
/// implemented separately for each specific platform.  These
/// platform-independent and platform-specific atomic operations together
/// form a full set of atomic operations for the 32-bit unsigned integer
/// type.
///
/// Note that `AtomicOperations_DefaultUint` is implemented in terms of the
/// following atomic operations on the integer type that must be provided by
/// the `IMP` template parameter.
/// ```
/// static int getInt(typename AtomicTypes::Int const *atomicInt);
/// static int getIntRelaxed(typename AtomicTypes::Int const *atomicInt);
/// static int getIntAcquire(typename AtomicTypes::Int const *atomicInt);
/// static void setInt(typename AtomicTypes::Int *atomicInt, int value);
/// static void setIntRelaxed(typename AtomicTypes::Int *atomicInt,
///                           int value);
/// static void setIntRelease(typename AtomicTypes::Int *atomicInt,
///                           int value);
/// static int swapInt(typename AtomicTypes::Int *atomicInt,
///                    int swapValue);
/// static int swapIntAcqRel(typename AtomicTypes::Int *atomicInt,
///                          int swapValue);
/// static int testAndSwapInt(typename AtomicTypes::Int *atomicInt,
///                           int compareValue,
///                           int swapValue);
/// static int testAndSwapIntAcqRel(typename AtomicTypes::Int *atomicInt,
///                                 int compareValue,
///                                 int swapValue);
/// ```
template <class IMP>
struct AtomicOperations_DefaultUint
{
  public:
    // PUBLIC TYPES
    typedef Atomic_TypeTraits<IMP> AtomicTypes;

    // CLASS METHODS

    /// Atomically retrieve the value of the specified `atomicUint`,
    /// providing the sequential consistency memory ordering guarantee.
    static unsigned int getUint(typename AtomicTypes::Uint const *atomicUint);

    /// Atomically retrieve the value of the specified `atomicUint`,
    /// providing the acquire memory ordering guarantee.
    static unsigned int getUintAcquire(
                                 typename AtomicTypes::Uint const *atomicUint);

    /// Atomically retrieve the value of the specified `atomicUint`, without
    /// providing any memory ordering guarantees.
    static unsigned int getUintRelaxed(
                                 typename AtomicTypes::Uint const *atomicUint);

    /// Initialize the specified `atomicUint` and set its value to the
    /// optionally specified `initialValue`.
    static void initUint(typename AtomicTypes::Uint *atomicUint,
                         unsigned int                initialValue = 0);

    /// Atomically set the value of the specified `atomicUint` to the
    /// specified `value`, providing the sequential consistency memory
    /// ordering guarantee.
    static void setUint(typename 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 setUintRelaxed(typename 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 void setUintRelease(typename AtomicTypes::Uint *atomicUint,
                               unsigned int                value);

    /// 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 swapUint(typename 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 swapUintAcqRel(typename AtomicTypes::Uint *atomicUint,
                                       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 testAndSwapUint(
                                      typename 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 unsigned int testAndSwapUintAcqRel(
                                      typename AtomicTypes::Uint *atomicUint,
                                      unsigned int                compareValue,
                                      unsigned int                swapValue);

    // Arithmetic

    /// Atomically add to the specified `atomicUint` the specified `value`,
    /// providing the sequential consistency memory ordering guarantee.
    static void addUint(typename AtomicTypes::Uint *atomicUint,
                        unsigned int                value);

    /// Atomically add to the specified `atomicUint` the specified `value`,
    /// providing the acquire/release memory ordering guarantee.
    static void addUintAcqRel(typename AtomicTypes::Uint *atomicUint,
                              unsigned int                value);

    /// Atomically add to the specified `atomicUint` the specified `value`,
    /// without providing any memory ordering guarantees.
    static void addUintRelaxed(typename 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 addUintNv(typename 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 addUintNvAcqRel(typename 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 unsigned int addUintNvRelaxed(
                                        typename AtomicTypes::Uint *atomicUint,
                                        unsigned int                value);

    /// Atomically decrement the value of the specified `atomicUint` by 1,
    /// providing the sequential consistency memory ordering guarantee.
    static void decrementUint(typename AtomicTypes::Uint *atomicUint);

    /// Atomically decrement the value of the specified `atomicUint` by 1,
    /// providing the acquire/release memory ordering guarantee.
    static void decrementUintAcqRel(typename 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 decrementUintNv(
                                       typename AtomicTypes::Uint *atomicUint);

    /// Atomically decrement the specified `atomicUint` by 1 and return the
    /// resulting value, providing the acquire/release memory ordering
    /// guarantee.
    static unsigned int decrementUintNvAcqRel(
                                       typename AtomicTypes::Uint *atomicUint);

    /// Atomically increment the value of the specified `atomicUint` by 1,
    /// providing the sequential consistency memory ordering guarantee.
    static void incrementUint(typename AtomicTypes::Uint *atomicUint);

    /// Atomically increment the value of the specified `atomicUint` by 1,
    /// providing the acquire/release memory ordering guarantee.
    static void incrementUintAcqRel(typename 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 incrementUintNv(
                                       typename 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 incrementUintNvAcqRel(
                                       typename AtomicTypes::Uint *atomicUint);

    /// Atomically subtract from the specified `atomicUint` the specified
    /// `value` and return the resulting value, providing the sequential
    /// consistency memory ordering guarantee.
    static unsigned int subtractUintNv(typename 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 subtractUintNvAcqRel(
                                        typename 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.
    static unsigned int subtractUintNvRelaxed(
                                        typename AtomicTypes::Uint *atomicUint,
                                        unsigned int                value);
};

                    // =====================================
                    // struct AtomicOperations_DefaultUint64
                    // =====================================

/// This class provides default implementations of non-essential atomic
/// operations for the 64-bit unsigned integer type independent on any
/// specific platform.  It also provides prototypes for the atomic
/// operations for the 64-bit unsigned integer type that have to be
/// implemented separately for each specific platform.  These
/// platform-independent and platform-specific atomic operations together
/// form a full set of atomic operations for the 64-bit unsigned integer
/// type.
///
/// Note that `AtomicOperations_DefaultUint64` is implemented in terms of
/// the following atomic operations on the Int64 type that must be provided
/// by the `IMP` template parameter.
/// ```
/// static Types::Int64 getInt64(
///                          typename AtomicTypes::Int64 const *atomicInt);
/// static Types::Int64 getInt64Relaxed(
///                          typename AtomicTypes::Int64 const *atomicInt);
/// static Types::Int64 getInt64Acquire(
///                          typename AtomicTypes::Int64 const *atomicInt);
/// static void setInt64(typename AtomicTypes::Int64 *atomicInt,
///                      Types::Int64 value);
/// static void setInt64Relaxed(typename AtomicTypes::Int64 *atomicInt,
///                             Types::Int64 value);
/// static void setInt64Release(typename AtomicTypes::Int64 *atomicInt,
///                             Types::Int64 value);
/// static Types::Int64 swapInt64(typename AtomicTypes::Int64 *atomicInt,
///                               Types::Int64 swapValue);
/// static Types::Int64 swapInt64AcqRel(
///                                 typename AtomicTypes::Int64 *atomicInt,
///                                 Types::Int64 swapValue);
/// static Types::Int64 testAndSwapInt64(
///                                 typename AtomicTypes::Int64 *atomicInt,
///                                 Types::Int64 compareValue,
///                                 Types::Int64 swapValue);
/// static Types::Int64 testAndSwapInt64AcqRel(
///                                 typename AtomicTypes::Int64 *atomicInt,
///                                 Types::Int64 compareValue,
///                                 Types::Int64 swapValue);
/// ```
template <class IMP>
struct AtomicOperations_DefaultUint64
{
  public:
    // PUBLIC TYPES
    typedef Atomic_TypeTraits<IMP> AtomicTypes;

    // CLASS METHODS

    /// Atomically retrieve the value of the specified `atomicUint`,
    /// providing the sequential consistency memory ordering guarantee.
    static Types::Uint64 getUint64(
                               typename AtomicTypes::Uint64 const *atomicUint);

    /// Atomically retrieve the value of the specified `atomicUint`,
    /// providing the acquire memory ordering guarantee.
    static Types::Uint64 getUint64Acquire(
                               typename AtomicTypes::Uint64 const *atomicUint);

    /// Atomically retrieve the value of the specified `atomicUint`, without
    /// providing any memory ordering guarantees.
    static Types::Uint64 getUint64Relaxed(
                               typename AtomicTypes::Uint64 const *atomicUint);

    /// Initialize the specified `atomicUint` and set its value to the
    /// optionally specified `initialValue`.
    static void initUint64(typename AtomicTypes::Uint64  *atomicUint,
                           Types::Uint64                  initialValue = 0);

    /// Atomically set the value of the specified `atomicUint` to the
    /// specified `value`, providing the sequential consistency memory
    /// ordering guarantee.
    static void setUint64(typename 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 setUint64Relaxed(typename 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 void setUint64Release(typename AtomicTypes::Uint64 *atomicUint,
                                 Types::Uint64                 value);

    /// 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 swapUint64(typename 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 swapUint64AcqRel(
                                      typename AtomicTypes::Uint64 *atomicUint,
                                      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 testAndSwapUint64(
                                    typename 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 Types::Uint64 testAndSwapUint64AcqRel(
                                    typename AtomicTypes::Uint64 *atomicUint,
                                    Types::Uint64                 compareValue,
                                    Types::Uint64                 swapValue);

    // Arithmetic

    /// Atomically add to the specified `atomicUint` the specified `value`,
    /// providing the sequential consistency memory ordering guarantee.
    static void addUint64(typename AtomicTypes::Uint64 *atomicUint,
                          Types::Uint64                 value);

    /// Atomically add to the specified `atomicUint` the specified `value`,
    /// providing the acquire/release memory ordering guarantee.
    static void addUint64AcqRel(typename AtomicTypes::Uint64 *atomicUint,
                                Types::Uint64                 value);

    /// Atomically add to the specified `atomicUint` the specified `value`,
    /// without providing any memory ordering guarantees.
    static void addUint64Relaxed(typename 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 addUint64Nv(typename 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 addUint64NvAcqRel(
                                      typename 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 Types::Uint64 addUint64NvRelaxed(
                                      typename AtomicTypes::Uint64 *atomicUint,
                                      Types::Uint64                 value);

    /// Atomically decrement the specified `atomicUint` by 1, providing the
    /// sequential consistency memory ordering guarantee.
    static void decrementUint64(typename AtomicTypes::Uint64 *atomicUint);

    /// Atomically decrement the specified `atomicUint` by 1, providing the
    /// acquire/release memory ordering guarantee.
    static void decrementUint64AcqRel(
                                     typename 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 decrementUint64Nv(
                                     typename AtomicTypes::Uint64 *atomicUint);

    /// Atomically decrement the specified `atomicUint` by 1 and return the
    /// resulting value, providing the acquire/release memory ordering
    /// guarantee.
    static Types::Uint64 decrementUint64NvAcqRel(
                                     typename AtomicTypes::Uint64 *atomicUint);

    /// Atomically increment the value of the specified `atomicUint` by 1,
    /// providing the sequential consistency memory ordering guarantee.
    static void incrementUint64(typename AtomicTypes::Uint64 *atomicUint);

    /// Atomically increment the value of the specified `atomicUint` by 1,
    /// providing the acquire/release memory ordering guarantee.
    static void incrementUint64AcqRel(
                                     typename 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 incrementUint64Nv(
                                     typename 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 incrementUint64NvAcqRel(
                                     typename AtomicTypes::Uint64 *atomicUint);

    /// Atomically subtract from the specified `atomicUint` the specified
    /// `value` and return the resulting value, providing the sequential
    /// consistency memory ordering guarantee.
    static Types::Uint64 subtractUint64Nv(
                                      typename 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 subtractUint64NvAcqRel(
                                      typename 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.
    static Types::Uint64 subtractUint64NvRelaxed(
                                      typename AtomicTypes::Uint64 *atomicUint,
                                      Types::Uint64                 value);
};

                  // ========================================
                  // struct AtomicOperations_DefaultPointer32
                  // ========================================

/// This class provides default implementations of non-essential atomic
/// operations for the 32-bit pointer type independent on any specific
/// platform.  It also provides prototypes for the atomic operations for the
/// pointer type that have to be implemented separately for each specific
/// platform.  These platform-independent and platform-specific atomic
/// operations combined together form a full set of atomic operations for
/// the pointer type.
///
/// Note that `AtomicOperations_DefaultPointer32` is implemented in terms of
/// the following atomic operations on the integer type that must be
/// provided by the `IMP` template parameter.
/// ```
/// static int getInt(typename AtomicTypes::Int const *atomicInt);
/// static int getIntRelaxed(typename AtomicTypes::Int const *atomicInt);
/// static int getIntAcquire(typename AtomicTypes::Int const *atomicInt);
/// static void setInt(typename AtomicTypes::Int *atomicInt, int value);
/// static void setIntRelaxed(typename AtomicTypes::Int *atomicInt,
///                           int value);
/// static void setIntRelease(typename AtomicTypes::Int *atomicInt,
///                           int value);
/// static int swapInt(typename AtomicTypes::Int *atomicInt,
///                    int swapValue);
/// static int swapIntAcqRel(typename AtomicTypes::Int *atomicInt,
///                          int swapValue);
/// static int testAndSwapInt(typename AtomicTypes::Int *atomicInt,
///                           int compareValue,
///                           int swapValue);
/// static int testAndSwapIntAcqRel(typename AtomicTypes::Int *atomicInt,
///                                 int compareValue,
///                                 int swapValue);
/// ```
template <class IMP>
struct AtomicOperations_DefaultPointer32
{
    // PUBLIC TYPES
    typedef Atomic_TypeTraits<IMP> AtomicTypes;

    // CLASS METHODS

    /// Atomically retrieve the value of the specified `atomicPtr`,
    /// providing the sequential consistency memory ordering guarantee.
    static void *getPtr(typename AtomicTypes::Pointer const *atomicPtr);

    /// Atomically retrieve the value of the specified `atomicPtr`,
    /// providing the acquire memory ordering guarantee.
    static void *getPtrAcquire(typename AtomicTypes::Pointer const *atomicPtr);

    /// Atomically retrieve the value of the specified `atomicPtr`, without
    /// providing any memory ordering guarantees.
    static void *getPtrRelaxed(typename AtomicTypes::Pointer const *atomicPtr);

    /// Initialize the specified `atomicPtr` and set its value to the
    /// optionally specified `initialValue`.
    static void initPointer(typename AtomicTypes::Pointer *atomicPtr,
                            void                          *initialValue = 0);

    /// Atomically set the value of the specified `atomicPtr` to the
    /// specified `value`, providing the sequential consistency memory
    /// ordering guarantee.
    static void setPtr(typename 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 setPtrRelaxed(typename 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 setPtrRelease(typename AtomicTypes::Pointer *atomicPtr,
                              void                          *value);

    /// 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 *swapPtr(typename 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 *swapPtrAcqRel(typename AtomicTypes::Pointer *atomicPtr,
                               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 *testAndSwapPtr(typename 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.
    static void *testAndSwapPtrAcqRel(
                                   typename AtomicTypes::Pointer *atomicPtr,
                                   void                          *compareValue,
                                   void                          *swapValue);
};

                  // ========================================
                  // struct AtomicOperations_DefaultPointer64
                  // ========================================

/// This class provides default implementations of non-essential atomic
/// operations for the 64-bit pointer type independent on any specific
/// platform.  It also provides prototypes for the atomic operations for the
/// pointer type that have to be implemented separately for each specific
/// platform.  These platform-independent and platform-specific atomic
/// operations combined together form a full set of atomic operations for
/// the pointer type.
///
/// Note that `AtomicOperations_DefaultPointer64` is implemented in terms of
/// the following atomic operations on the Int64 type that must be provided
/// by the `IMP` template parameter.
/// ```
/// static Types::Int64 getInt64(
///                          typename AtomicTypes::Int64 const *atomicInt);
/// static Types::Int64 getInt64Relaxed(
///                          typename AtomicTypes::Int64 const *atomicInt);
/// static Types::Int64 getInt64Acquire(
///                          typename AtomicTypes::Int64 const *atomicInt);
/// static void setInt64(typename AtomicTypes::Int64 *atomicInt,
///                      Types::Int64 value);
/// static void setInt64Relaxed(typename AtomicTypes::Int64 *atomicInt,
///                             Types::Int64 value);
/// static void setInt64Release(typename AtomicTypes::Int64 *atomicInt,
///                             Types::Int64 value);
/// static Types::Int64 swapInt64(typename AtomicTypes::Int64 *atomicInt,
///                               Types::Int64 swapValue);
/// static Types::Int64 swapInt64AcqRel(
///                                 typename AtomicTypes::Int64 *atomicInt,
///                                 Types::Int64 swapValue);
/// static Types::Int64 testAndSwapInt64(
///                                 typename AtomicTypes::Int64 *atomicInt,
///                                 Types::Int64 compareValue,
///                                 Types::Int64 swapValue);
/// static Types::Int64 testAndSwapInt64AcqRel(
///                                 typename AtomicTypes::Int64 *atomicInt,
///                                 Types::Int64 compareValue,
///                                 Types::Int64 swapValue);
/// ```
template <class IMP>
struct AtomicOperations_DefaultPointer64
{
    // PUBLIC TYPES
    typedef Atomic_TypeTraits<IMP> AtomicTypes;

    // CLASS METHODS

    /// Atomically retrieve the value of the specified `atomicPtr`,
    /// providing the sequential consistency memory ordering guarantee.
    static void *getPtr(typename AtomicTypes::Pointer const *atomicPtr);

    /// Atomically retrieve the value of the specified `atomicPtr`,
    /// providing the acquire memory ordering guarantee.
    static void *getPtrAcquire(typename AtomicTypes::Pointer const *atomicPtr);

    /// Atomically retrieve the value of the specified `atomicPtr`, without
    /// providing any memory ordering guarantees.
    static void *getPtrRelaxed(typename AtomicTypes::Pointer const *atomicPtr);

    /// Initialize the specified `atomicPtr` and set its value to the
    /// optionally specified `initialValue`.
    static void initPointer(typename AtomicTypes::Pointer *atomicPtr,
                            void                          *initialValue = 0);

    /// Atomically set the value of the specified `atomicPtr` to the
    /// specified `value`, providing the sequential consistency memory
    /// ordering guarantee.
    static void setPtr(typename 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 setPtrRelaxed(typename 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 setPtrRelease(typename AtomicTypes::Pointer *atomicPtr,
                              void                          *value);

    /// 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 *swapPtr(typename 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 *swapPtrAcqRel(typename AtomicTypes::Pointer *atomicPtr,
                               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 *testAndSwapPtr(typename 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.
    static void *testAndSwapPtrAcqRel(
                                   typename AtomicTypes::Pointer *atomicPtr,
                                   void                          *compareValue,
                                   void                          *swapValue);
};

                      // =================================
                      // struct AtomicOperations_Default32
                      // =================================

/// This class provides default implementations of non-essential atomic
/// operations for the 32-bit integer, 64-bit integer, the 32-bit unsigned
/// integer, 64-bit unsigned integer and 32-bit pointer type for a generic
/// 32-bit platform.
template <class IMP>
struct AtomicOperations_Default32
: AtomicOperations_DefaultInt<IMP>
, AtomicOperations_DefaultInt64<IMP>
, AtomicOperations_DefaultUint<IMP>
, AtomicOperations_DefaultUint64<IMP>
, AtomicOperations_DefaultPointer32<IMP>
{
};

                      // =================================
                      // struct AtomicOperations_Default64
                      // =================================

/// This class provides default implementations of non-essential atomic
/// operations for the 32-bit integer, 64-bit integer, the 32-bit unsigned
/// integer, 64-bit unsigned integer and 64-bit pointer type for a generic
/// 64-bit platform.
template <class IMP>
struct AtomicOperations_Default64
: AtomicOperations_DefaultInt<IMP>
, AtomicOperations_DefaultInt64<IMP>
, AtomicOperations_DefaultUint<IMP>
, AtomicOperations_DefaultUint64<IMP>
, AtomicOperations_DefaultPointer64<IMP>
{
};

// ============================================================================
//                        INLINE FUNCTION DEFINITIONS
// ============================================================================

                     // ----------------------------------
                     // struct AtomicOperations_DefaultInt
                     // ----------------------------------

// CLASS METHODS
template <class IMP>
inline
int AtomicOperations_DefaultInt<IMP>::
    getIntAcquire(typename AtomicTypes::Int const *atomicInt)
{
    return IMP::getInt(atomicInt);
}

template <class IMP>
inline
int AtomicOperations_DefaultInt<IMP>::
    getIntRelaxed(typename AtomicTypes::Int const *atomicInt)
{
    return atomicInt->d_value;
}

template <class IMP>
inline
void AtomicOperations_DefaultInt<IMP>::
    initInt(typename AtomicTypes::Int *atomicInt, int initialValue)
{
    atomicInt->d_value = initialValue;
}

template <class IMP>
inline
void AtomicOperations_DefaultInt<IMP>::
    setIntRelaxed(typename AtomicTypes::Int *atomicInt, int value)
{
    atomicInt->d_value = value;
}

template <class IMP>
inline
void AtomicOperations_DefaultInt<IMP>::
    setIntRelease(typename AtomicTypes::Int *atomicInt, int value)
{
    IMP::setInt(atomicInt, value);
}

template <class IMP>
inline
int AtomicOperations_DefaultInt<IMP>::
    swapIntAcqRel(typename AtomicTypes::Int *atomicInt, int swapValue)
{
    return IMP::swapInt(atomicInt, swapValue);
}

template <class IMP>
inline
int AtomicOperations_DefaultInt<IMP>::testAndSwapIntAcqRel(
                                       typename AtomicTypes::Int *atomicInt,
                                       int                        compareValue,
                                       int                        swapValue)
{
    return IMP::testAndSwapInt(atomicInt, compareValue, swapValue);
}

// Arithmetic
template <class IMP>
inline
void AtomicOperations_DefaultInt<IMP>::
    addInt(typename AtomicTypes::Int *atomicInt, int value)
{
    IMP::addIntNv(atomicInt, value);
}

template <class IMP>
inline
void AtomicOperations_DefaultInt<IMP>::
    addIntAcqRel(typename AtomicTypes::Int *atomicInt, int value)
{
    IMP::addIntNvAcqRel(atomicInt, value);
}

template <class IMP>
inline
void AtomicOperations_DefaultInt<IMP>::
    addIntRelaxed(typename AtomicTypes::Int *atomicInt, int value)
{
    IMP::addIntNvRelaxed(atomicInt, value);
}

template <class IMP>
inline
int AtomicOperations_DefaultInt<IMP>::
    addIntNvAcqRel(typename AtomicTypes::Int *atomicInt, int value)
{
    return IMP::addIntNv(atomicInt, value);
}

template <class IMP>
inline
int AtomicOperations_DefaultInt<IMP>::
    addIntNvRelaxed(typename AtomicTypes::Int *atomicInt, int value)
{
    return IMP::addIntNvAcqRel(atomicInt, value);
}

template <class IMP>
inline
void AtomicOperations_DefaultInt<IMP>::
    decrementInt(typename AtomicTypes::Int *atomicInt)
{
    IMP::addInt(atomicInt, -1);
}

template <class IMP>
inline
void AtomicOperations_DefaultInt<IMP>::
    decrementIntAcqRel(typename AtomicTypes::Int *atomicInt)
{
    IMP::addIntAcqRel(atomicInt, -1);
}

template <class IMP>
inline
int AtomicOperations_DefaultInt<IMP>::
    decrementIntNv(typename AtomicTypes::Int *atomicInt)
{
    return IMP::addIntNv(atomicInt, -1);
}

template <class IMP>
inline
int AtomicOperations_DefaultInt<IMP>::
    decrementIntNvAcqRel(typename AtomicTypes::Int *atomicInt)
{
    return IMP::addIntNvAcqRel(atomicInt, -1);
}

template <class IMP>
inline
void AtomicOperations_DefaultInt<IMP>::
    incrementInt(typename AtomicTypes::Int *atomicInt)
{
    IMP::addInt(atomicInt, 1);
}

template <class IMP>
inline
void AtomicOperations_DefaultInt<IMP>::
    incrementIntAcqRel(typename AtomicTypes::Int *atomicInt)
{
    IMP::addIntAcqRel(atomicInt, 1);
}

template <class IMP>
inline
int AtomicOperations_DefaultInt<IMP>::
    incrementIntNv(typename AtomicTypes::Int *atomicInt)
{
    return IMP::addIntNv(atomicInt, 1);
}

template <class IMP>
inline
int AtomicOperations_DefaultInt<IMP>::
    incrementIntNvAcqRel(typename AtomicTypes::Int *atomicInt)
{
    return IMP::addIntNvAcqRel(atomicInt, 1);
}

template <class IMP>
inline
int AtomicOperations_DefaultInt<IMP>::
    subtractIntNv(typename AtomicTypes::Int *atomicInt, int value)
{
    return static_cast<int>(
        IMP::subtractUintNv(
            reinterpret_cast<typename AtomicTypes::Uint *>(atomicInt),
            static_cast<unsigned int>(value)));
}

template <class IMP>
inline
int AtomicOperations_DefaultInt<IMP>::
    subtractIntNvAcqRel(typename AtomicTypes::Int *atomicInt, int value)
{
    return static_cast<int>(
        IMP::subtractUintNvAcqRel(
            reinterpret_cast<typename AtomicTypes::Uint *>(atomicInt),
            static_cast<unsigned int>(value)));
}

template <class IMP>
inline
int AtomicOperations_DefaultInt<IMP>::
    subtractIntNvRelaxed(typename AtomicTypes::Int *atomicInt, int value)
{
    return static_cast<int>(
        IMP::subtractUintNvRelaxed(
            reinterpret_cast<typename AtomicTypes::Uint *>(atomicInt),
            static_cast<unsigned int>(value)));
}

                    // ------------------------------------
                    // struct AtomicOperations_DefaultInt64
                    // ------------------------------------

// CLASS METHODS
template <class IMP>
inline
Types::Int64 AtomicOperations_DefaultInt64<IMP>::
    getInt64Acquire(typename AtomicTypes::Int64 const *atomicInt)
{
    return IMP::getInt64(atomicInt);
}

template <class IMP>
inline
Types::Int64 AtomicOperations_DefaultInt64<IMP>::
    getInt64Relaxed(typename AtomicTypes::Int64 const *atomicInt)
{
    return atomicInt->d_value;
}

template <class IMP>
inline
void AtomicOperations_DefaultInt64<IMP>::initInt64(
                                    typename AtomicTypes::Int64  *atomicInt,
                                    Types::Int64                  initialValue)
{
    atomicInt->d_value = initialValue;
}

template <class IMP>
inline
void AtomicOperations_DefaultInt64<IMP>::setInt64Relaxed(
                                        typename AtomicTypes::Int64 *atomicInt,
                                        Types::Int64                 value)
{
    atomicInt->d_value = value;
}

template <class IMP>
inline
void AtomicOperations_DefaultInt64<IMP>::setInt64Release(
                                        typename AtomicTypes::Int64 *atomicInt,
                                        Types::Int64                 value)
{
    IMP::setInt64(atomicInt, value);
}

template <class IMP>
inline
Types::Int64 AtomicOperations_DefaultInt64<IMP>::swapInt64AcqRel(
                                        typename AtomicTypes::Int64 *atomicInt,
                                        Types::Int64                 swapValue)
{
    return IMP::swapInt64(atomicInt, swapValue);
}

template <class IMP>
inline
Types::Int64 AtomicOperations_DefaultInt64<IMP>::testAndSwapInt64AcqRel(
                                     typename AtomicTypes::Int64 *atomicInt,
                                     Types::Int64                 compareValue,
                                     Types::Int64                 swapValue)
{
    return IMP::testAndSwapInt64(atomicInt, compareValue, swapValue);
}

// Arithmetic
template <class IMP>
inline
void AtomicOperations_DefaultInt64<IMP>::addInt64(
                                        typename AtomicTypes::Int64 *atomicInt,
                                        Types::Int64                 value)
{
    IMP::addInt64Nv(atomicInt, value);
}

template <class IMP>
inline
void AtomicOperations_DefaultInt64<IMP>::addInt64AcqRel(
                                        typename AtomicTypes::Int64 *atomicInt,
                                        Types::Int64                 value)
{
    IMP::addInt64NvAcqRel(atomicInt, value);
}

template <class IMP>
inline
void AtomicOperations_DefaultInt64<IMP>::addInt64Relaxed(
                                        typename AtomicTypes::Int64 *atomicInt,
                                        Types::Int64                 value)
{
    IMP::addInt64NvRelaxed(atomicInt, value);
}

template <class IMP>
inline
Types::Int64 AtomicOperations_DefaultInt64<IMP>::addInt64NvAcqRel(
                                        typename AtomicTypes::Int64 *atomicInt,
                                        Types::Int64                 value)
{
    return IMP::addInt64Nv(atomicInt, value);
}

template <class IMP>
inline
Types::Int64 AtomicOperations_DefaultInt64<IMP>::addInt64NvRelaxed(
                                        typename AtomicTypes::Int64 *atomicInt,
                                        Types::Int64                 value)
{
    return IMP::addInt64NvAcqRel(atomicInt, value);
}

template <class IMP>
inline
void AtomicOperations_DefaultInt64<IMP>::
    decrementInt64(typename AtomicTypes::Int64 *atomicInt)
{
    IMP::addInt64(atomicInt, -1);
}

template <class IMP>
inline
void AtomicOperations_DefaultInt64<IMP>::
    decrementInt64AcqRel(typename AtomicTypes::Int64 *atomicInt)
{
    IMP::addInt64AcqRel(atomicInt, -1);
}

template <class IMP>
inline
Types::Int64 AtomicOperations_DefaultInt64<IMP>::
    decrementInt64Nv(typename AtomicTypes::Int64 *atomicInt)
{
    return IMP::addInt64Nv(atomicInt, -1);
}

template <class IMP>
inline
Types::Int64 AtomicOperations_DefaultInt64<IMP>::
    decrementInt64NvAcqRel(typename AtomicTypes::Int64 *atomicInt)
{
    return IMP::addInt64NvAcqRel(atomicInt, -1);
}

template <class IMP>
inline
void AtomicOperations_DefaultInt64<IMP>::
    incrementInt64(typename AtomicTypes::Int64 *atomicInt)
{
    IMP::addInt64(atomicInt, 1);
}

template <class IMP>
inline
void AtomicOperations_DefaultInt64<IMP>::
    incrementInt64AcqRel(typename AtomicTypes::Int64 *atomicInt)
{
    IMP::addInt64AcqRel(atomicInt, 1);
}

template <class IMP>
inline
Types::Int64 AtomicOperations_DefaultInt64<IMP>::
    incrementInt64Nv(typename AtomicTypes::Int64 *atomicInt)
{
    return IMP::addInt64Nv(atomicInt, 1);
}

template <class IMP>
inline
Types::Int64 AtomicOperations_DefaultInt64<IMP>::
    incrementInt64NvAcqRel(typename AtomicTypes::Int64 *atomicInt)
{
    return IMP::addInt64NvAcqRel(atomicInt, 1);
}

template <class IMP>
inline
Types::Int64 AtomicOperations_DefaultInt64<IMP>::subtractInt64Nv(
                                        typename AtomicTypes::Int64 *atomicInt,
                                        Types::Int64                 value)
{
    return static_cast<Types::Int64>(
        IMP::subtractUint64Nv(
            reinterpret_cast<typename AtomicTypes::Uint64 *>(atomicInt),
            static_cast<Types::Uint64>(value)));
}

template <class IMP>
inline
Types::Int64 AtomicOperations_DefaultInt64<IMP>::subtractInt64NvAcqRel(
                                        typename AtomicTypes::Int64 *atomicInt,
                                        Types::Int64                 value)
{
    return static_cast<Types::Int64>(
        IMP::subtractUint64NvAcqRel(
            reinterpret_cast<typename AtomicTypes::Uint64 *>(atomicInt),
            static_cast<Types::Uint64>(value)));
}

template <class IMP>
inline
Types::Int64 AtomicOperations_DefaultInt64<IMP>::subtractInt64NvRelaxed(
                                        typename AtomicTypes::Int64 *atomicInt,
                                        Types::Int64                 value)
{
    return static_cast<Types::Int64>(
        IMP::subtractUint64NvRelaxed(
            reinterpret_cast<typename AtomicTypes::Uint64 *>(atomicInt),
            static_cast<Types::Uint64>(value)));
}

                     // ----------------------------------
                     // struct AtomicOperations_DefaultUint
                     // ----------------------------------

// CLASS METHODS
template <class IMP>
inline
unsigned int AtomicOperations_DefaultUint<IMP>::
    getUint(typename AtomicTypes::Uint const *atomicUint)
{
    return static_cast<unsigned int>(
              IMP::getInt(
                  reinterpret_cast<typename AtomicTypes::Int const *>(
                      atomicUint)));
}

template <class IMP>
inline
unsigned int AtomicOperations_DefaultUint<IMP>::
    getUintAcquire(typename AtomicTypes::Uint const *atomicUint)
{
    return static_cast<unsigned int>(
        IMP::getIntAcquire(
             reinterpret_cast<typename AtomicTypes::Int const *>(atomicUint)));
}

template <class IMP>
inline
unsigned int AtomicOperations_DefaultUint<IMP>::
    getUintRelaxed(typename AtomicTypes::Uint const *atomicUint)
{
    return static_cast<unsigned int>(
        IMP::getIntRelaxed(
             reinterpret_cast<typename AtomicTypes::Int const *>(atomicUint)));
}

template <class IMP>
inline
void AtomicOperations_DefaultUint<IMP>::
    initUint(typename AtomicTypes::Uint *atomicUint, unsigned int initialValue)
{
    atomicUint->d_value = initialValue;
}

template <class IMP>
inline
void AtomicOperations_DefaultUint<IMP>::
    setUint(typename AtomicTypes::Uint *atomicUint, unsigned int value)
{
    IMP::setInt(reinterpret_cast<typename AtomicTypes::Int *>(atomicUint),
                static_cast<int>(value));
}

template <class IMP>
inline
void AtomicOperations_DefaultUint<IMP>::
    setUintRelaxed(typename AtomicTypes::Uint *atomicUint, unsigned int value)
{
    IMP::setIntRelaxed(
        reinterpret_cast<typename AtomicTypes::Int *>(atomicUint),
                static_cast<int>(value));
}

template <class IMP>
inline
void AtomicOperations_DefaultUint<IMP>::
    setUintRelease(typename AtomicTypes::Uint *atomicUint, unsigned int value)
{
    IMP::setIntRelease(
        reinterpret_cast<typename AtomicTypes::Int *>(atomicUint),
                static_cast<int>(value));
}

template <class IMP>
inline
unsigned int AtomicOperations_DefaultUint<IMP>::
    swapUint(typename AtomicTypes::Uint *atomicUint, unsigned int swapValue)
{
    return static_cast<unsigned int>(
             IMP::swapInt(
                 reinterpret_cast<typename AtomicTypes::Int *>(atomicUint),
                 static_cast<int>(swapValue)));
}

template <class IMP>
inline
unsigned int AtomicOperations_DefaultUint<IMP>::swapUintAcqRel(
                                        typename AtomicTypes::Uint *atomicUint,
                                        unsigned int                swapValue)
{
    return static_cast<unsigned int>(
        IMP::swapIntAcqRel(
                reinterpret_cast<typename AtomicTypes::Int *>(atomicUint),
                static_cast<int>(swapValue)));
}

template <class IMP>
inline
unsigned int AtomicOperations_DefaultUint<IMP>::testAndSwapUint(
                           typename AtomicTypes::Uint            *atomicUint,
                           unsigned int                           compareValue,
                           unsigned int                           swapValue)
{
    return static_cast<unsigned int>(
             IMP::testAndSwapInt(
                 reinterpret_cast<typename AtomicTypes::Int *>(atomicUint),
                                 static_cast<int>(compareValue),
                                 static_cast<int>(swapValue)));
}

template <class IMP>
inline
unsigned int AtomicOperations_DefaultUint<IMP>::testAndSwapUintAcqRel(
                                      typename AtomicTypes::Uint *atomicUint,
                                      unsigned int                compareValue,
                                      unsigned int                swapValue)
{
    return static_cast<unsigned int>(
             IMP::testAndSwapIntAcqRel(
                 reinterpret_cast<typename AtomicTypes::Int *>(atomicUint),
                                 static_cast<int>(compareValue),
                                 static_cast<int>(swapValue)));
}

// Arithmetic
template <class IMP>
inline
void AtomicOperations_DefaultUint<IMP>::
    addUint(typename AtomicTypes::Uint *atomicUint, unsigned int value)
{
        IMP::addInt(reinterpret_cast<typename AtomicTypes::Int *>(atomicUint),
                        static_cast<int>(value));
}

template <class IMP>
inline
void AtomicOperations_DefaultUint<IMP>::
    addUintAcqRel(typename AtomicTypes::Uint *atomicUint, unsigned int value)
{
    IMP::addIntAcqRel(
        reinterpret_cast<typename AtomicTypes::Int *>(atomicUint),
        static_cast<int>(value));
}

template <class IMP>
inline
void AtomicOperations_DefaultUint<IMP>::
    addUintRelaxed(typename AtomicTypes::Uint *atomicUint, unsigned int value)
{
    IMP::addIntRelaxed(
        reinterpret_cast<typename AtomicTypes::Int *>(atomicUint),
        static_cast<int>(value));
}

template <class IMP>
inline
unsigned int AtomicOperations_DefaultUint<IMP>::
    addUintNv(typename AtomicTypes::Uint *atomicUint, unsigned int value)
{
    return static_cast<unsigned int>(
             IMP::addIntNv(
                 reinterpret_cast<typename AtomicTypes::Int *>(atomicUint),
                     static_cast<int>(value)));
}

template <class IMP>
inline
unsigned int AtomicOperations_DefaultUint<IMP>::
    addUintNvAcqRel(typename AtomicTypes::Uint *atomicUint, unsigned int value)
{
    return static_cast<unsigned int>(
        IMP::addIntNvAcqRel(
                reinterpret_cast<typename AtomicTypes::Int *>(atomicUint),
                static_cast<int>(value)));
}

template <class IMP>
inline
unsigned int AtomicOperations_DefaultUint<IMP>::addUintNvRelaxed(
                                        typename AtomicTypes::Uint *atomicUint,
                                        unsigned int                value)
{
    return static_cast<unsigned int>(
        IMP::addIntNvRelaxed(
                reinterpret_cast<typename AtomicTypes::Int *>(atomicUint),
                static_cast<int>(value)));
}

template <class IMP>
inline
void AtomicOperations_DefaultUint<IMP>::
    decrementUint(typename AtomicTypes::Uint *atomicUint)
{
    IMP::addInt(reinterpret_cast<typename AtomicTypes::Int *>(atomicUint), -1);
}

template <class IMP>
inline
void AtomicOperations_DefaultUint<IMP>::
    decrementUintAcqRel(typename AtomicTypes::Uint *atomicUint)
{
    IMP::addIntAcqRel(
                reinterpret_cast<typename AtomicTypes::Int *>(atomicUint), -1);
}

template <class IMP>
inline
unsigned int AtomicOperations_DefaultUint<IMP>::
    decrementUintNv(typename AtomicTypes::Uint *atomicUint)
{
    return IMP::subtractUintNv(atomicUint, 1);
}

template <class IMP>
inline
unsigned int AtomicOperations_DefaultUint<IMP>::
    decrementUintNvAcqRel(typename AtomicTypes::Uint *atomicUint)
{
    return static_cast<unsigned int>(
       IMP::addIntNvAcqRel(
               reinterpret_cast<typename AtomicTypes::Int *>(atomicUint), -1));
}

template <class IMP>
inline
void AtomicOperations_DefaultUint<IMP>::
    incrementUint(typename AtomicTypes::Uint *atomicUint)
{
    IMP::addUint(atomicUint, 1);
}

template <class IMP>
inline
void AtomicOperations_DefaultUint<IMP>::
    incrementUintAcqRel(typename AtomicTypes::Uint *atomicUint)
{
    IMP::addUintAcqRel(atomicUint, 1);
}

template <class IMP>
inline
unsigned int AtomicOperations_DefaultUint<IMP>::
    incrementUintNv(typename AtomicTypes::Uint *atomicUint)
{
    return IMP::addUintNv(atomicUint, 1);
}

template <class IMP>
inline
unsigned int AtomicOperations_DefaultUint<IMP>::
    incrementUintNvAcqRel(typename AtomicTypes::Uint *atomicUint)
{
    return IMP::addUintNvAcqRel(atomicUint, 1);
}

template <class IMP>
inline
unsigned int AtomicOperations_DefaultUint<IMP>::
    subtractUintNv(typename AtomicTypes::Uint *atomicUint, unsigned int value)
{
    return static_cast<unsigned int>(
             IMP::addIntNv(
                 reinterpret_cast<typename AtomicTypes::Int *>(atomicUint),
                     static_cast<int>(1 + ~value)));
}

template <class IMP>
inline
unsigned int AtomicOperations_DefaultUint<IMP>::subtractUintNvAcqRel(
                                        typename AtomicTypes::Uint *atomicUint,
                                        unsigned int                value)
{
    return static_cast<unsigned int>(
        IMP::addIntNvAcqRel(
                reinterpret_cast<typename AtomicTypes::Int *>(atomicUint),
                static_cast<int>(1 + ~value)));
}

template <class IMP>
inline
unsigned int AtomicOperations_DefaultUint<IMP>::subtractUintNvRelaxed(
                                        typename AtomicTypes::Uint *atomicUint,
                                        unsigned int                value)
{
    return static_cast<unsigned int>(
        IMP::addIntNvRelaxed(
                reinterpret_cast<typename AtomicTypes::Int *>(atomicUint),
                static_cast<int>(1 + ~value)));
}

                    // ------------------------------------
                    // struct AtomicOperations_DefaultUint64
                    // ------------------------------------

// CLASS METHODS
template <class IMP>
inline
Types::Uint64 AtomicOperations_DefaultUint64<IMP>::
    getUint64(typename AtomicTypes::Uint64 const *atomicUint)
{
    return static_cast<Types::Uint64>(
        IMP::getInt64(reinterpret_cast<typename AtomicTypes::Int64 const *>(
                      atomicUint)));
}

template <class IMP>
inline
Types::Uint64 AtomicOperations_DefaultUint64<IMP>::
    getUint64Acquire(typename AtomicTypes::Uint64 const *atomicUint)
{
    return static_cast<Types::Uint64>(IMP::getInt64Acquire(
        reinterpret_cast<typename AtomicTypes::Int64 const *>(atomicUint)));
}

template <class IMP>
inline
Types::Uint64 AtomicOperations_DefaultUint64<IMP>::
    getUint64Relaxed(typename AtomicTypes::Uint64 const *atomicUint)
{
    return static_cast<Types::Uint64>(IMP::getInt64Relaxed(
        reinterpret_cast<typename AtomicTypes::Int64 const *>(atomicUint)));
}

template <class IMP>
inline
void AtomicOperations_DefaultUint64<IMP>::initUint64(
                                   typename AtomicTypes::Uint64  *atomicUint,
                                   Types::Uint64                  initialValue)
{
    atomicUint->d_value = initialValue;
}

template <class IMP>
inline
void AtomicOperations_DefaultUint64<IMP>::
    setUint64(typename AtomicTypes::Uint64 *atomicUint, Types::Uint64 value)
{
    IMP::setInt64(reinterpret_cast<typename AtomicTypes::Int64 *>(atomicUint),
                  static_cast<Types::Int64>(value));
}

template <class IMP>
inline
void AtomicOperations_DefaultUint64<IMP>::setUint64Relaxed(
                                      typename AtomicTypes::Uint64 *atomicUint,
                                      Types::Uint64                 value)
{
    IMP::setInt64Relaxed(
        reinterpret_cast<typename AtomicTypes::Int64 *>(atomicUint),
        static_cast<Types::Int64>(value));
}

template <class IMP>
inline
void AtomicOperations_DefaultUint64<IMP>::setUint64Release(
                                      typename AtomicTypes::Uint64 *atomicUint,
                                      Types::Uint64                 value)
{
    IMP::setInt64Release(
        reinterpret_cast<typename AtomicTypes::Int64 *>(atomicUint),
        static_cast<Types::Int64>(value));
}

template <class IMP>
inline
Types::Uint64 AtomicOperations_DefaultUint64<IMP>::swapUint64(
                                      typename AtomicTypes::Uint64 *atomicUint,
                                      Types::Uint64                 swapValue)
{
    return static_cast<Types::Uint64>(
              IMP::swapInt64(
                   reinterpret_cast<typename AtomicTypes::Int64 *>(atomicUint),
                   static_cast<Types::Int64>(swapValue)));
}

template <class IMP>
inline
Types::Uint64 AtomicOperations_DefaultUint64<IMP>::swapUint64AcqRel(
                                      typename AtomicTypes::Uint64 *atomicUint,
                                      Types::Uint64                 swapValue)
{
    return static_cast<Types::Uint64>(
        IMP::swapInt64AcqRel(
            reinterpret_cast<typename AtomicTypes::Int64 *>(atomicUint),
            static_cast<Types::Int64>(swapValue)));
}

template <class IMP>
inline
Types::Uint64 AtomicOperations_DefaultUint64<IMP>::testAndSwapUint64(
                                    typename AtomicTypes::Uint64 *atomicUint,
                                    Types::Uint64                 compareValue,
                                    Types::Uint64                 swapValue)
{
    return static_cast<Types::Uint64>(
              IMP::testAndSwapInt64(
                  reinterpret_cast<typename AtomicTypes::Int64 *>(atomicUint),
                  static_cast<Types::Int64>(compareValue),
                  static_cast<Types::Int64>(swapValue)));
}

template <class IMP>
inline
Types::Uint64 AtomicOperations_DefaultUint64<IMP>::testAndSwapUint64AcqRel(
                                    typename AtomicTypes::Uint64 *atomicUint,
                                    Types::Uint64                 compareValue,
                                    Types::Uint64                 swapValue)
{
    return static_cast<Types::Uint64>(
        IMP::testAndSwapInt64AcqRel(
                  reinterpret_cast<typename AtomicTypes::Int64 *>(atomicUint),
                  static_cast<Types::Int64>(compareValue),
                  static_cast<Types::Int64>(swapValue)));
}

// Arithmetic
template <class IMP>
inline
void AtomicOperations_DefaultUint64<IMP>::addUint64(
                  typename AtomicTypes::Uint64 *atomicUint,Types::Uint64 value)
{
    IMP::addInt64(reinterpret_cast<typename AtomicTypes::Int64 *>(atomicUint),
                     static_cast<Types::Int64>(value));
}

template <class IMP>
inline
void AtomicOperations_DefaultUint64<IMP>::addUint64AcqRel(
                  typename AtomicTypes::Uint64 *atomicUint,Types::Uint64 value)
{
    IMP::addInt64AcqRel(
        reinterpret_cast<typename AtomicTypes::Int64 *>(atomicUint),
        static_cast<Types::Int64>(value));
}

template <class IMP>
inline
void AtomicOperations_DefaultUint64<IMP>::addUint64Relaxed(
                  typename AtomicTypes::Uint64 *atomicUint,Types::Uint64 value)
{
    IMP::addInt64Relaxed(
        reinterpret_cast<typename AtomicTypes::Int64 *>(atomicUint),
        static_cast<Types::Int64>(value));
}

template <class IMP>
inline
Types::Uint64 AtomicOperations_DefaultUint64<IMP>::addUint64Nv(
                  typename AtomicTypes::Uint64 *atomicUint,Types::Uint64 value)
{
    return static_cast<Types::Uint64>(
              IMP::addInt64Nv(
                  reinterpret_cast<typename AtomicTypes::Int64 *>(atomicUint),
                  static_cast<Types::Int64>(value)));
}

template <class IMP>
inline
Types::Uint64 AtomicOperations_DefaultUint64<IMP>::addUint64NvAcqRel(
                  typename AtomicTypes::Uint64 *atomicUint,Types::Uint64 value)
{
    return static_cast<Types::Uint64>(
        IMP::addInt64NvAcqRel(
            reinterpret_cast<typename AtomicTypes::Int64 *>(atomicUint),
            static_cast<Types::Int64>(value)));
}

template <class IMP>
inline
Types::Uint64 AtomicOperations_DefaultUint64<IMP>::addUint64NvRelaxed(
                  typename AtomicTypes::Uint64 *atomicUint,Types::Uint64 value)
{
    return static_cast<Types::Uint64>(
        IMP::addInt64NvRelaxed(
            reinterpret_cast<typename AtomicTypes::Int64 *>(atomicUint),
            static_cast<Types::Int64>(value)));
}

template <class IMP>
inline
void AtomicOperations_DefaultUint64<IMP>::
    decrementUint64(typename AtomicTypes::Uint64 *atomicUint)
{
    IMP::addInt64(reinterpret_cast<typename AtomicTypes::Int64 *>(atomicUint),
                  -1);
}

template <class IMP>
inline
void AtomicOperations_DefaultUint64<IMP>::
    decrementUint64AcqRel(typename AtomicTypes::Uint64 *atomicUint)
{
        IMP::addInt64AcqRel(
              reinterpret_cast<typename AtomicTypes::Int64 *>(atomicUint), -1);
}

template <class IMP>
inline
Types::Uint64 AtomicOperations_DefaultUint64<IMP>::
    decrementUint64Nv(typename AtomicTypes::Uint64 *atomicUint)
{
    return IMP::subtractUint64Nv(atomicUint, 1);
}

template <class IMP>
inline
Types::Uint64 AtomicOperations_DefaultUint64<IMP>::
    decrementUint64NvAcqRel(typename AtomicTypes::Uint64 *atomicUint)
{
    return static_cast<Types::Uint64>(
        IMP::addInt64NvAcqRel(
             reinterpret_cast<typename AtomicTypes::Int64 *>(atomicUint), -1));
}

template <class IMP>
inline
void AtomicOperations_DefaultUint64<IMP>::
    incrementUint64(typename AtomicTypes::Uint64 *atomicUint)
{
    IMP::addUint64(atomicUint, 1);
}

template <class IMP>
inline
void AtomicOperations_DefaultUint64<IMP>::
    incrementUint64AcqRel(typename AtomicTypes::Uint64 *atomicUint)
{
    IMP::addUint64AcqRel(atomicUint, 1);
}

template <class IMP>
inline
Types::Uint64 AtomicOperations_DefaultUint64<IMP>::
    incrementUint64Nv(typename AtomicTypes::Uint64 *atomicUint)
{
    return IMP::addUint64Nv(atomicUint, 1);
}

template <class IMP>
inline
Types::Uint64 AtomicOperations_DefaultUint64<IMP>::
    incrementUint64NvAcqRel(typename AtomicTypes::Uint64 *atomicUint)
{
    return IMP::addUint64NvAcqRel(atomicUint, 1);
}

template <class IMP>
inline
Types::Uint64 AtomicOperations_DefaultUint64<IMP>::subtractUint64Nv(
                 typename AtomicTypes::Uint64 *atomicUint, Types::Uint64 value)
{
    return static_cast<Types::Uint64>(
              IMP::addInt64Nv(
                  reinterpret_cast<typename AtomicTypes::Int64 *>(atomicUint),
                  static_cast<Types::Int64>(1 + ~value)));
}

template <class IMP>
inline
Types::Uint64 AtomicOperations_DefaultUint64<IMP>::subtractUint64NvAcqRel(
                  typename AtomicTypes::Uint64 *atomicUint,Types::Uint64 value)
{
    return static_cast<Types::Uint64>(
        IMP::addInt64NvAcqRel(
            reinterpret_cast<typename AtomicTypes::Int64 *>(atomicUint),
            static_cast<Types::Int64>(1 + ~value)));
}

template <class IMP>
inline
Types::Uint64 AtomicOperations_DefaultUint64<IMP>::subtractUint64NvRelaxed(
                  typename AtomicTypes::Uint64 *atomicUint,Types::Uint64 value)
{
    return static_cast<Types::Uint64>(
        IMP::addInt64NvRelaxed(
            reinterpret_cast<typename AtomicTypes::Int64 *>(atomicUint),
            static_cast<Types::Int64>(1 + ~value)));
}

                  // ----------------------------------------
                  // struct AtomicOperations_DefaultPointer32
                  // ----------------------------------------

// CLASS METHODS
template <class IMP>
inline
void *AtomicOperations_DefaultPointer32<IMP>::
    getPtr(typename AtomicTypes::Pointer const *atomicPtr)
{
    return reinterpret_cast<void *>(
             IMP::getInt(
                reinterpret_cast<typename AtomicTypes::Int const *>(
                    atomicPtr)));
}

template <class IMP>
inline
void *AtomicOperations_DefaultPointer32<IMP>::
    getPtrAcquire(typename AtomicTypes::Pointer const *atomicPtr)
{
    return reinterpret_cast<void *>(
             IMP::getIntAcquire(
                reinterpret_cast<typename AtomicTypes::Int const *>(
                    atomicPtr)));
}

template <class IMP>
inline
void *AtomicOperations_DefaultPointer32<IMP>::
    getPtrRelaxed(typename AtomicTypes::Pointer const *atomicPtr)
{
    return reinterpret_cast<void *>(
             IMP::getIntRelaxed(
                reinterpret_cast<typename AtomicTypes::Int const *>(
                    atomicPtr)));
}

template <class IMP>
inline
void AtomicOperations_DefaultPointer32<IMP>::initPointer(
                  typename AtomicTypes::Pointer *atomicPtr, void *initialValue)
{
    atomicPtr->d_value = initialValue;
}

template <class IMP>
inline
void AtomicOperations_DefaultPointer32<IMP>::setPtr(
                         typename AtomicTypes::Pointer *atomicPtr, void *value)
{
    IMP::setInt(
        reinterpret_cast<typename AtomicTypes::Int *>(atomicPtr),
        reinterpret_cast<Types::IntPtr>(value));
}

template <class IMP>
inline
void AtomicOperations_DefaultPointer32<IMP>::setPtrRelaxed(
                         typename AtomicTypes::Pointer *atomicPtr, void *value)
{
    IMP::setIntRelaxed(
        reinterpret_cast<typename AtomicTypes::Int *>(atomicPtr),
        reinterpret_cast<Types::IntPtr>(value));
}

template <class IMP>
inline
void AtomicOperations_DefaultPointer32<IMP>::setPtrRelease(
                         typename AtomicTypes::Pointer *atomicPtr, void *value)
{
    IMP::setIntRelease(
        reinterpret_cast<typename AtomicTypes::Int *>(atomicPtr),
        reinterpret_cast<Types::IntPtr>(value));
}

template <class IMP>
inline
void *AtomicOperations_DefaultPointer32<IMP>::swapPtr(
                     typename AtomicTypes::Pointer *atomicPtr, void *swapValue)
{
    return reinterpret_cast<void *>(
            IMP::swapInt(
                reinterpret_cast<typename AtomicTypes::Int *>(atomicPtr),
                reinterpret_cast<Types::IntPtr>(swapValue)));
}

template <class IMP>
inline
void *AtomicOperations_DefaultPointer32<IMP>::swapPtrAcqRel(
                     typename AtomicTypes::Pointer *atomicPtr, void *swapValue)
{
    return reinterpret_cast<void *>(
            IMP::swapIntAcqRel(
                reinterpret_cast<typename AtomicTypes::Int *>(atomicPtr),
                reinterpret_cast<Types::IntPtr>(swapValue)));
}

template <class IMP>
inline
void *AtomicOperations_DefaultPointer32<IMP>::testAndSwapPtr(
                                   typename AtomicTypes::Pointer *atomicPtr,
                                   void                          *compareValue,
                                   void                          *swapValue)
{
    return reinterpret_cast<void *>(
            IMP::testAndSwapInt(
                reinterpret_cast<typename AtomicTypes::Int *>(atomicPtr),
                reinterpret_cast<Types::IntPtr>(compareValue),
                reinterpret_cast<Types::IntPtr>(swapValue)));
}

template <class IMP>
inline
void *AtomicOperations_DefaultPointer32<IMP>::testAndSwapPtrAcqRel(
                                   typename AtomicTypes::Pointer *atomicPtr,
                                   void                          *compareValue,
                                   void                          *swapValue)
{
    return reinterpret_cast<void *>(
            IMP::testAndSwapIntAcqRel(
                reinterpret_cast<typename AtomicTypes::Int *>(atomicPtr),
                reinterpret_cast<Types::IntPtr>(compareValue),
                reinterpret_cast<Types::IntPtr>(swapValue)));
}

                  // ----------------------------------------
                  // struct AtomicOperations_DefaultPointer64
                  // ----------------------------------------

// CLASS METHODS
template <class IMP>
inline
void *AtomicOperations_DefaultPointer64<IMP>::
    getPtr(typename AtomicTypes::Pointer const *atomicPtr)
{
    return reinterpret_cast<void *>(
             IMP::getInt64(
                reinterpret_cast<typename AtomicTypes::Int64 const *>(
                    atomicPtr)));
}

template <class IMP>
inline
void *AtomicOperations_DefaultPointer64<IMP>::
    getPtrAcquire(typename AtomicTypes::Pointer const *atomicPtr)
{
    return reinterpret_cast<void *>(
             IMP::getInt64Acquire(
                reinterpret_cast<typename AtomicTypes::Int64 const *>(
                    atomicPtr)));
}

template <class IMP>
inline
void *AtomicOperations_DefaultPointer64<IMP>::
    getPtrRelaxed(typename AtomicTypes::Pointer const *atomicPtr)
{
    return reinterpret_cast<void *>(
             IMP::getInt64Relaxed(
                reinterpret_cast<typename AtomicTypes::Int64 const *>(
                    atomicPtr)));
}

template <class IMP>
inline
void AtomicOperations_DefaultPointer64<IMP>::initPointer(
                  typename AtomicTypes::Pointer *atomicPtr, void *initialValue)
{
    atomicPtr->d_value = initialValue;
}

template <class IMP>
inline
void AtomicOperations_DefaultPointer64<IMP>::setPtr(
                         typename AtomicTypes::Pointer *atomicPtr, void *value)
{
    IMP::setInt64(
        reinterpret_cast<typename AtomicTypes::Int64 *>(atomicPtr),
        reinterpret_cast<Types::IntPtr>(value));
}

template <class IMP>
inline
void AtomicOperations_DefaultPointer64<IMP>::setPtrRelaxed(
                         typename AtomicTypes::Pointer *atomicPtr, void *value)
{
    IMP::setInt64Relaxed(
        reinterpret_cast<typename AtomicTypes::Int64 *>(atomicPtr),
        reinterpret_cast<Types::IntPtr>(value));
}

template <class IMP>
inline
void AtomicOperations_DefaultPointer64<IMP>::setPtrRelease(
                         typename AtomicTypes::Pointer *atomicPtr, void *value)
{
    IMP::setInt64Release(
        reinterpret_cast<typename AtomicTypes::Int64 *>(atomicPtr),
        reinterpret_cast<Types::IntPtr>(value));
}

template <class IMP>
inline
void *AtomicOperations_DefaultPointer64<IMP>::swapPtr(
                     typename AtomicTypes::Pointer *atomicPtr, void *swapValue)
{
    return reinterpret_cast<void *>(
            IMP::swapInt64(
                reinterpret_cast<typename AtomicTypes::Int64 *>(atomicPtr),
                reinterpret_cast<Types::IntPtr>(swapValue)));
}

template <class IMP>
inline
void *AtomicOperations_DefaultPointer64<IMP>::swapPtrAcqRel(
                     typename AtomicTypes::Pointer *atomicPtr, void *swapValue)
{
    return reinterpret_cast<void *>(
            IMP::swapInt64AcqRel(
                reinterpret_cast<typename AtomicTypes::Int64 *>(atomicPtr),
                reinterpret_cast<Types::IntPtr>(swapValue)));
}

template <class IMP>
inline
void *AtomicOperations_DefaultPointer64<IMP>::testAndSwapPtr(
                                   typename AtomicTypes::Pointer *atomicPtr,
                                   void                          *compareValue,
                                   void                          *swapValue)
{
    return reinterpret_cast<void *>(
            IMP::testAndSwapInt64(
                reinterpret_cast<typename AtomicTypes::Int64 *>(atomicPtr),
                reinterpret_cast<Types::IntPtr>(compareValue),
                reinterpret_cast<Types::IntPtr>(swapValue)));
}

template <class IMP>
inline
void *AtomicOperations_DefaultPointer64<IMP>::testAndSwapPtrAcqRel(
                                   typename AtomicTypes::Pointer *atomicPtr,
                                   void                          *compareValue,
                                   void                          *swapValue)
{
    return reinterpret_cast<void *>(
            IMP::testAndSwapInt64AcqRel(
                reinterpret_cast<typename AtomicTypes::Int64 *>(atomicPtr),
                reinterpret_cast<Types::IntPtr>(compareValue),
                reinterpret_cast<Types::IntPtr>(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 ----------------------------------
