// 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:
//: o bsls::AtomicOperations_DefaultInt - provides atomic operations for int
//: o bsls::AtomicOperations_DefaultInt64 - for Int64
//: o bsls::AtomicOperations_DefaultPointer32 - for 32-bit pointer
//: o 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:
//
//: o bsls::AtomicOperations_Default32 - a set of atomic operations for a
//:   generic 32-bit platform
//:
//: o bsls::AtomicOperations_Default64 - a set of atomic operations for a
//:   generic 64-bit platform
//
// This is how the generic platform base classes are composed:
//: o bsls::AtomicOperations_Default32 : AtomicOperations_DefaultInt,
//:   AtomicOperations_DefaultInt64, AtomicOperations_DefaultPointer32
//: o 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;

template <class IMP>
struct AtomicOperations_DefaultInt
    // 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.
{
  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
    static int addIntNv(typename AtomicTypes::Int *atomicInt, int value);
        // Atomically add to the specified 'atomicInt' the specified 'value'
        // and return the resulting value, providing the sequential consistency
        // memory ordering guarantee.

    static int getInt(typename AtomicTypes::Int const *atomicInt);
        // Atomically retrieve the value of the specified 'atomicInt',
        // 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 'value', providing the sequential consistency memory
        // ordering guarantee.

    static int swapInt(typename AtomicTypes::Int *atomicInt, int swapValue);
        // Atomically set the value of the specified 'atomicInt' to the
        // specified 'swapValue', and return its previous value, providing the
        // sequential consistency memory ordering guarantee.

    static int testAndSwapInt(typename AtomicTypes::Int *atomicInt,
                              int                        compareValue,
                              int                        swapValue);
        // Conditionally set the value of the specified 'atomicInt' to the
        // specified 'swapValue' if and only if the value of 'atomicInt' equals
        // the value of the specified 'compareValue', and return the initial
        // value of 'atomicInt', providing the sequential consistency memory
        // ordering guarantee.  The whole operation is performed atomically.

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

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

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

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

    static void setIntRelease(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 int swapIntAcqRel(typename AtomicTypes::Int *atomicInt,
                             int                        swapValue);
        // Atomically set the value of the specified 'atomicInt' to the
        // specified 'swapValue', and return its previous value, providing the
        // acquire/release memory ordering guarantee.

    static int testAndSwapIntAcqRel(typename AtomicTypes::Int *atomicInt,
                                    int                        compareValue,
                                    int                        swapValue);
        // Conditionally set the value of the specified 'atomicInt' to the
        // specified 'swapValue' if and only if the value of 'atomicInt' equals
        // the value of the specified 'compareValue', and return the initial
        // value of 'atomicInt', providing the acquire/release memory ordering
        // guarantee.  The whole operation is performed atomically.

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

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

    static void addIntRelaxed(typename AtomicTypes::Int *atomicInt, int value);
        // Atomically add to the specified 'atomicInt' the specified 'value',
        // without providing any memory ordering guarantees.

    static int addIntNvAcqRel(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 addIntNvRelaxed(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 void decrementInt(typename AtomicTypes::Int *atomicInt);
        // Atomically decrement the value of the specified 'atomicInt' by 1,
        // providing the sequential consistency memory ordering guarantee.

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

    static int decrementIntNv(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 decrementIntNvAcqRel(typename AtomicTypes::Int *atomicInt);
        // Atomically decrement the specified 'atomicInt' by 1 and return the
        // resulting value, providing the acquire/release memory ordering
        // guarantee.

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

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

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

    static int subtractIntNvAcqRel(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 subtractIntNvRelaxed(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.
};

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

template <class IMP>
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.
{
  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
    static Types::Int64 addInt64Nv(typename AtomicTypes::Int64 *atomicInt,
                                   Types::Int64                 value);
        // Atomically add to the specified 'atomicInt' the specified 'value'
        // and return the resulting value, providing the sequential consistency
        // memory ordering guarantee.

    static Types::Int64 getInt64(typename AtomicTypes::Int64 const *atomicInt);
        // Atomically retrieve the value of the specified 'atomicInt',
        // 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 'value', providing the sequential consistency memory
        // ordering guarantee.

    static Types::Int64 swapInt64(typename AtomicTypes::Int64 *atomicInt,
                                  Types::Int64                 swapValue);
        // Atomically set the value of the specified 'atomicInt' to the
        // specified 'swapValue' and return its previous value, providing the
        // sequential consistency memory ordering guarantee.

    static Types::Int64 testAndSwapInt64(
                                     typename AtomicTypes::Int64 *atomicInt,
                                     Types::Int64                 compareValue,
                                     Types::Int64                 swapValue);
        // Conditionally set the value of the specified 'atomicInt' to the
        // specified 'swapValue' if and only if the value of 'atomicInt' equals
        // the value of the specified 'compareValue', and return the initial
        // value of 'atomicInt', providing the sequential consistency memory
        // ordering guarantee.  The whole operation is performed atomically.

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

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

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

    static void setInt64Relaxed(typename AtomicTypes::Int64 *atomicInt,
                                Types::Int64                 value);
        // Atomically set the value of the specified 'atomicInt' to the
        // specified 'value', without providing any memory ordering guarantees.

    static void setInt64Release(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 Types::Int64 swapInt64AcqRel(
                                       typename AtomicTypes::Int64 *atomicInt,
                                       Types::Int64                 swapValue);
        // Atomically set the value of the specified 'atomicInt' to the
        // specified 'swapValue' and return its previous value, providing the
        // acquire/release memory ordering guarantee.

    static Types::Int64 testAndSwapInt64AcqRel(
                                     typename AtomicTypes::Int64 *atomicInt,
                                     Types::Int64                 compareValue,
                                     Types::Int64                 swapValue);
        // Conditionally set the value of the specified 'atomicInt' to the
        // specified 'swapValue' if and only if the value of 'atomicInt' equals
        // the value of the specified 'compareValue', and return the initial
        // value of 'atomicInt', providing the sequential consistency memory
        // ordering guarantee.  The whole operation is performed atomically.

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

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

    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, providing the acquire/release memory
        // ordering guarantee.

    static Types::Int64 addInt64NvRelaxed(
                                        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 void decrementInt64(typename AtomicTypes::Int64 *atomicInt);
        // Atomically decrement the specified 'atomicInt' by 1, providing the
        // sequential consistency memory ordering guarantee.

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

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

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

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

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

    static Types::Int64 subtractInt64NvAcqRel(
                                        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 subtractInt64NvRelaxed(
                                        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.
};

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

template <class IMP>
struct Atomic_TypeTraits;

template <class IMP>
struct AtomicOperations_DefaultUint
    // 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);
    //..
{
  public:
    // PUBLIC TYPES
    typedef Atomic_TypeTraits<IMP> AtomicTypes;

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

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

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

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

    static void setUint(typename AtomicTypes::Uint *atomicUint,
                        unsigned int                value);
        // Atomically set the value of the specified 'atomicUint' to the
        // specified 'value', providing the sequential consistency memory
        // ordering guarantee.

    static void setUintRelaxed(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 setUintRelease(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 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
        // sequential consistency memory ordering guarantee.

    static unsigned int swapUintAcqRel(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 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 'atomicUint'
        // equals the value of the specified 'compareValue', and return the
        // initial value of 'atomicUint', providing the sequential consistency
        // memory ordering guarantee.  The whole operation is performed
        // atomically.

    static unsigned int testAndSwapUintAcqRel(
                                      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.

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

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

    static unsigned int addUintNv(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 addUintNvAcqRel(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 addUintNvRelaxed(
                                        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 void decrementUint(typename AtomicTypes::Uint *atomicUint);
        // Atomically decrement the value of the specified 'atomicUint' by 1,
        // providing the sequential consistency memory ordering guarantee.

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

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

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

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

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

    static unsigned int subtractUintNvAcqRel(
                                        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 subtractUintNvRelaxed(
                                        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.
};

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

template <class IMP>
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);
    //..
{
  public:
    // PUBLIC TYPES
    typedef Atomic_TypeTraits<IMP> AtomicTypes;

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

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

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

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

    static void setUint64(typename AtomicTypes::Uint64 *atomicUint,
                          Types::Uint64                 value);
        // Atomically set the value of the specified 'atomicUint' to the
        // specified 'value', providing the sequential consistency memory
        // ordering guarantee.

    static void setUint64Relaxed(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 setUint64Release(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 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
        // sequential consistency memory ordering guarantee.

    static Types::Uint64 swapUint64AcqRel(
                                      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 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 sequential consistency
        // memory ordering guarantee.  The whole operation is performed
        // atomically.

    static Types::Uint64 testAndSwapUint64AcqRel(
                                    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.

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

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

    static Types::Uint64 addUint64Nv(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 addUint64NvAcqRel(
                                      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 addUint64NvRelaxed(
                                      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 void decrementUint64(typename AtomicTypes::Uint64 *atomicUint);
        // Atomically decrement the specified 'atomicUint' by 1, providing the
        // sequential consistency memory ordering guarantee.

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

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

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

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

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

    static Types::Uint64 subtractUint64NvAcqRel(
                                      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 subtractUint64NvRelaxed(
                                      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.
};

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

template <class IMP>
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);
    //..
{
    // PUBLIC TYPES
    typedef Atomic_TypeTraits<IMP> AtomicTypes;

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

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

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

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

    static void setPtr(typename AtomicTypes::Pointer *atomicPtr,
                       void                          *value);
        // Atomically set the value of the specified 'atomicPtr' to the
        // specified 'value', providing the sequential consistency memory
        // ordering guarantee.

    static void setPtrRelaxed(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 setPtrRelease(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 *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
        // sequential consistency memory ordering guarantee.

    static void *swapPtrAcqRel(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 *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 sequential consistency memory
        // ordering guarantee.  The whole operation is performed atomically.

    static void *testAndSwapPtrAcqRel(
                                   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.
};

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

template <class IMP>
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);
    //..
{
    // PUBLIC TYPES
    typedef Atomic_TypeTraits<IMP> AtomicTypes;

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

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

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

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

    static void setPtr(typename AtomicTypes::Pointer *atomicPtr,
                       void                          *value);
        // Atomically set the value of the specified 'atomicPtr' to the
        // specified 'value', providing the sequential consistency memory
        // ordering guarantee.

    static void setPtrRelaxed(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 setPtrRelease(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 *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
        // sequential consistency memory ordering guarantee.

    static void *swapPtrAcqRel(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 *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 sequential consistency memory
        // ordering guarantee.  The whole operation is performed atomically.

    static void *testAndSwapPtrAcqRel(
                                   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.
};

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

template <class IMP>
struct AtomicOperations_Default32
: AtomicOperations_DefaultInt<IMP>
, AtomicOperations_DefaultInt64<IMP>
, AtomicOperations_DefaultUint<IMP>
, AtomicOperations_DefaultUint64<IMP>
, AtomicOperations_DefaultPointer32<IMP>
    // 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.
{
};

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

template <class IMP>
struct AtomicOperations_Default64
: AtomicOperations_DefaultInt<IMP>
, AtomicOperations_DefaultInt64<IMP>
, AtomicOperations_DefaultUint<IMP>
, AtomicOperations_DefaultUint64<IMP>
, AtomicOperations_DefaultPointer64<IMP>
    // 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.
{
};

// ============================================================================
//                        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 atomicUint->d_value;
}

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)
{
    atomicUint->d_value = 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 atomicUint->d_value;
}

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)
{
    atomicUint->d_value = 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 ----------------------------------