// bslma_default.h                                                    -*-C++-*-
#ifndef INCLUDED_BSLMA_DEFAULT
#define INCLUDED_BSLMA_DEFAULT

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

//@PURPOSE: Provide utilities to set/fetch the default and global allocators.
//
//@CLASSES:
//  bslma::Default: namespace for default/global allocator management utilities
//
//@SEE_ALSO: bslma_allocator, bslma_newdeleteallocator
//
//@DESCRIPTION: This component provides a set of utility functions that manage
// the addresses of two distinguished memory allocators: the *default*
// allocator and the *global* allocator.  Each of these allocators are of type
// derived from 'bslma::Allocator'.  Note that for brevity, in the following we
// will generally refer to "the address of the default allocator" as simply
// "the default allocator" (and similarly for the global allocator).
//
// The global allocator is intended to be used as the allocator for (global)
// singleton objects.  In general, the default allocator is for all other
// memory allocations in contexts where an alternative allocator is not
// explicitly specified (or *cannot* be specified as, for example, when a
// compiler-generated temporary object of a type that requires an allocator is
// created).
//
// Initially, both the default allocator and global allocator resolve to the
// address of the 'bslma::NewDeleteAllocator' singleton, i.e.:
//..
//  &bslma::NewDeleteAllocator::singleton()
//..
// Methods are provided to retrieve and set the two allocators independently.
// The following two subsections supply further details, in turn, on the
// methods that pertain to the default and global allocators.
//
///Default Allocator
///-----------------
// Two methods provide access to the default allocator,
// 'bslma::Default::defaultAllocator' and 'bslma::Default::allocator' (the
// latter when called with no argument, or an explicit 0).  When
// 'bslma::Default::allocator' is supplied with a non-0 argument, it simply
// returns that argument to the caller, (i.e., it acts as a pass-through).  A
// (non-singleton) class that is designed to take advantage of an allocator
// will typically revert to the default allocator whenever a constructor is
// called without an allocator (yielding the default argument value of 0).  The
// 'bslma::Default::allocator' method facilitates this behavior.  See the usage
// examples below for an illustration of this technique.
//
// The default allocator can be set *prior* to a call to
// 'bslma::Default::defaultAllocator', to 'bslma::Default::allocator' with no
// argument or an explicit 0, or to 'bslma::Default::lockDefaultAllocator', by
// calling 'bslma::Default::setDefaultAllocator'.  This method returns 0 on
// success and a non-zero value on failure.  This method fails if the default
// allocator is "locked".  The default allocator is initially unlocked.  It is
// *explicitly* locked by calling 'bslma::Default::lockDefaultAllocator'.  In
// addition, the default allocator is *implicitly* locked as a *side-effect* of
// calling 'bslma::Default::defaultAllocator', or 'bslma::Default::allocator'
// with no argument or an explicit 0.  Once locked, the default allocator
// cannot be unlocked.  However, the 'bslma::Default::setDefaultAllocatorRaw'
// method will unconditionally set the default allocator regardless of whether
// it is locked.
//
// A well-behaved program should call 'bslma::Default::setDefaultAllocator'
// *once*.  It should be invoked in 'main' before starting any threads, and be
// followed immediately by a call to 'bslma::Default::lockDefaultAllocator.
// Note that 'bslma::Default::setDefaultAllocatorRaw' is provided for *testing*
// *only*, and should typically *never* be used in a production environment.
//
// *WARNING*: Note that the default allocator can become locked prior to
// entering 'main' as a side-effect of initializing a file-scope static object.
// For example, the presence of a global 'bsl::string' object in an executable
// will have this unintended consequence.  Further note that this phenomenon
// can *vary* *across* *platforms*.  In particular, linkers differ as to the
// aggressiveness with which they pull in file-scope static objects from the
// libraries that are on the link line.  *AVOID* file-scope static objects that
// require runtime initialization, *especially* those that take an allocator.
//
///Global Allocator
///----------------
// The interface pertaining to the global allocator is comparatively much
// simpler, consisting of just two methods.  The
// 'bslma::Default::globalAllocator' method, when called with no argument (or
// an explicit 0), returns the global allocator currently in effect at the
// point of call.  It has *no* side-effects.  When supplied with a non-0
// argument, 'bslma::Default::globalAllocator' simply returns that argument to
// the caller (i.e., it acts as a pass-through similar to
// 'bslma::Default::allocator' when it is supplied with a non-0 argument).  The
// global allocator may be set using the 'bslma::Default::setGlobalAllocator'
// method.  This method *always* succeeds.  In that respect, the global
// allocator cannot become locked like the default allocator.
// 'bslma::Default::setGlobalAllocator' returns the global allocator that is in
// effect upon entry to the function.
//
// Note that 'bslma::Default::setGlobalAllocator' should be used with *extreme*
// *caution*.  In particular, a well-behaved program should call this function
// at most once.  If called, it should be invoked in 'main' before starting any
// threads and before initializing singletons.
//
///Usage
///-----
// The following sequence of usage examples illustrate recommended use of the
// default and global allocators.  The examples employ the following simple
// memory allocator, 'my_CountingAllocator', that counts both the number of
// memory blocks that have been allocated, but not yet deallocated, and the
// cumulative number of blocks ever allocated.  The two values are available
// through the accessors 'numBlocksInUse' and 'numBlocksTotal', respectively.
// For actual allocations and deallocations, 'my_CountingAllocator' uses global
// operators 'new' and 'delete':
//..
//  // my_countingallocator.h
//  #include <bslma_allocator.h>
//
//  class my_CountingAllocator : public bslma::Allocator {
//      // This concrete allocator maintains: (1) a count of the number of
//      // blocks allocated that have not yet been deallocated, and (2) a count
//      // of the cumulative number of blocks ever allocated.
//
//      // DATA
//      int d_numBlocksInUse;  // number of blocks currently allocated
//      int d_numBlocksTotal;  // cumulative blocks ever requested
//
//      // NOT IMPLEMENTED
//      my_CountingAllocator(const my_CountingAllocator&);
//      my_CountingAllocator& operator=(const my_CountingAllocator&);
//
//    public:
//      // CREATORS
//      my_CountingAllocator();
//          // Create a counting allocator.
//
//      virtual ~my_CountingAllocator();
//          // Destroy this counting allocator.
//
//      // MANIPULATORS
//      virtual void *allocate(size_type size);
//          // Return a newly allocated block of memory of (at least) the
//          // specified positive 'size' (bytes).  If 'size' is 0, a null
//          // pointer is returned with no effect.  Note that the alignment of
//          // the address returned is the maximum alignment for any
//          // fundamental type defined for this platform.
//
//      virtual void deallocate(void *address);
//          // Return the memory at the specified 'address' back to this
//          // allocator.  If 'address' is 0, this function has no effect.  The
//          // behavior is undefined if 'address' was not allocated using this
//          // allocator, or has already been deallocated.
//
//      // ACCESSORS
//      int numBlocksInUse() const;
//          // Return the number of blocks currently in use from this counting
//          // allocator.
//
//      int numBlocksTotal() const;
//          // Return the cumulative number of blocks ever allocated using this
//          // counting allocator.  Note that
//          // numBlocksTotal() >= numBlocksInUse().
//  };
//
//  // CREATORS
//  inline
//  my_CountingAllocator::my_CountingAllocator()
//  : d_numBlocksInUse(0)
//  , d_numBlocksTotal(0)
//  {
//  }
//
//  // ACCESSORS
//  inline
//  int my_CountingAllocator::numBlocksInUse() const
//  {
//      return d_numBlocksInUse;
//  }
//
//  inline
//  int my_CountingAllocator::numBlocksTotal() const
//  {
//      return d_numBlocksTotal;
//  }
//..
// The 'virtual' methods of 'my_CountingAllocator' are defined in the component
// '.cpp' file:
//..
//  // my_countingallocator.cpp
//  #include <my_countingallocator.h>
//
//  // CREATORS
//  my_CountingAllocator::~my_CountingAllocator()
//  {
//  }
//
//  // MANIPULATORS
//  void *my_CountingAllocator::allocate(size_type size)
//  {
//      ++d_numBlocksInUse;
//      ++d_numBlocksTotal;
//      return ::operator new(size);
//  }
//
//  void my_CountingAllocator::deallocate(void *address)
//  {
//      --d_numBlocksInUse;
//      ::operator delete(address);
//  }
//..
//
///Example 1: Basic Default Allocator Use
/// - - - - - - - - - - - - - - - - - - -
// This usage example illustrates the basics of class design that relate to
// proper use of the default allocator, and introduces the standard pattern to
// apply when setting (and *locking*) the default allocator.  First we define a
// trivial class, 'my_Id', that uses an allocator.  'my_Id' simply encapsulates
// a C-style (null-terminated) id string that is accessible through the 'id'
// method.  Note that each constructor is declared to take an *optional*
// 'bslma::Allocator *' as its last argument.  Also note that the expression:
//..
//  bslma::Default::allocator(basicAllocator)
//..
// is used in applicable member initializers to propagate each constructor's
// allocator argument to the data members that require it (in this case, the
// object allocator that is held by each 'my_Id' object).  If 'basicAllocator'
// is 0, the object is created using the default allocator.  Otherwise, the
// explicitly supplied allocator is used:
//..
//  // my_id.h
//  #include <bslma_allocator.h>
//  #include <bslma_default.h>
//
//  class my_Id {
//      // This is a trivial class solely intended to illustrate proper use
//      // of the default allocator.
//
//      // DATA
//      char             *d_buffer_p;     // allocated (*owned*)
//      bslma::Allocator *d_allocator_p;  // allocator (held, not owned)
//
//      // NOT IMPLEMENTED (in order to reduce example size)
//      my_Id& operator=(const my_Id&);
//
//    public:
//      // CREATORS
//      explicit my_Id(const char *id, bslma::Allocator *basicAllocator = 0);
//          // Create an Id object having the specified 'id'.  Optionally
//          // specify a 'basicAllocator' used to supply memory.  If
//          // 'basicAllocator' is 0, the currently installed default allocator
//          // is used.
//
//      my_Id(const my_Id& original, bslma::Allocator *basicAllocator = 0);
//          // Create an Id object initialized to the value of the specified
//          // 'original' Id object.  Optionally specify a 'basicAllocator'
//          // used to supply memory.  If 'basicAllocator' is 0, the currently
//          // installed default allocator is used.
//
//      ~my_Id();
//          // Destroy this Id object.
//
//      // ACCESSORS
//      const char *id() const;
//          // Return the id of this Id object.
//  };
//
//  // CREATORS
//  inline
//  my_Id::my_Id(const char *id, bslma::Allocator *basicAllocator)
//  : d_allocator_p(bslma::Default::allocator(basicAllocator))
//  {
//      d_buffer_p = (char *)d_allocator_p->allocate(std::strlen(id) + 1);
//      std::strcpy(d_buffer_p, id);
//  }
//
//  inline
//  my_Id::my_Id(const my_Id& original, bslma::Allocator *basicAllocator)
//  : d_allocator_p(bslma::Default::allocator(basicAllocator))
//  {
//      const char *id = original.id();
//      d_buffer_p = (char *)d_allocator_p->allocate(std::strlen(id) + 1);
//      std::strcpy(d_buffer_p, id);
//  }
//
//  inline
//  my_Id::~my_Id()
//  {
//      d_allocator_p->deallocate(d_buffer_p);
//  }
//
//  // ACCESSORS
//  inline
//  const char *my_Id::id() const
//  {
//      return d_buffer_p;
//  }
//..
// Next we set the default allocator to one of our counting allocator objects.
// Note that immediately after successfully setting it, we lock the default
// allocator, so that subsequent calls to 'bslma::Default::setDefaultAllocator'
// fail.  (The default allocator can still be modified by calling
// 'bslma::Default::setDefaultAllocatorRaw', but calling that function in
// production code is anti-social.  Our usage examples expressly do *not* call
// that method.)  With the possible exception of test drivers, the default
// allocator should be set and locked early in 'main' before threads are
// started and before objects are initialized:
//..
//  static my_CountingAllocator defaultCountingAllocator;
//
//  int status =
//              bslma::Default::setDefaultAllocator(&defaultCountingAllocator);
//  assert(0 == status);
//  bslma::Default::lockDefaultAllocator();  // subsequent calls to "set" fail
//  assert(bslma::Default::defaultAllocator() == &defaultCountingAllocator);
//
//  status = bslma::Default::setDefaultAllocator(
//                                    &bslma::NewDeleteAllocator::singleton());
//  assert(0 != status);
//  assert(bslma::Default::defaultAllocator() == &defaultCountingAllocator);
//..
// In the following, we instantiate two objects of type 'my_Id'.  The first
// object, 'idA', is not supplied with an allocator, so it uses the default
// allocator.  The second object, 'idB', is supplied with an object of type
// 'my_CountingAllocator'.  The assertions track the states of the two
// allocators at each point in the code fragment.  In particular, note that the
// state of the default allocator does not change during the lifetime of 'idB':
//..
//  assert(0 == defaultCountingAllocator.numBlocksInUse());
//  assert(0 == defaultCountingAllocator.numBlocksTotal());
//  {
//      my_Id id("A");
//      assert(1 == defaultCountingAllocator.numBlocksInUse());
//      assert(1 == defaultCountingAllocator.numBlocksTotal());
//  }
//  assert(0 == defaultCountingAllocator.numBlocksInUse());
//  assert(1 == defaultCountingAllocator.numBlocksTotal());
//
//  my_CountingAllocator objectCountingAllocator;
//  assert(0 == objectCountingAllocator.numBlocksInUse());
//  assert(0 == objectCountingAllocator.numBlocksTotal());
//  {
//      my_Id idB("B", &objectCountingAllocator);
//      assert(1 == objectCountingAllocator.numBlocksInUse());
//      assert(1 == objectCountingAllocator.numBlocksTotal());
//      assert(0 == defaultCountingAllocator.numBlocksInUse());
//      assert(1 == defaultCountingAllocator.numBlocksTotal());
//  }
//  assert(0 == objectCountingAllocator.numBlocksInUse());
//  assert(1 == objectCountingAllocator.numBlocksTotal());
//  assert(0 == defaultCountingAllocator.numBlocksInUse());
//  assert(1 == defaultCountingAllocator.numBlocksTotal());
//..
//
///Example 2: Detecting Allocator Propagation Bugs
///- - - - - - - - - - - - - - - - - - - - - - - -
// This example demonstrates how the default allocator is used to detect a very
// common programming error pertaining to allocator usage.  First we define the
// trivial (but buggy) 'my_IdPair' class:
//..
//  // my_idpair.h
//  #include <my_id.h>
//  #include <bslma_default.h>
//
//  class my_IdPair {
//      // This is a trivial class solely intended to help illustrate a common
//      // programming error.  This class has two objects of type 'my_Id', only
//      // one of which has the allocator correctly passed to it in the
//      // definition of the constructor.
//
//      // DATA
//      my_Id d_id;     // primary id (allocating)
//      my_Id d_alias;  // alias (allocating)
//
//      // NOT IMPLEMENTED (in order to reduce example size)
//      my_IdPair(const my_IdPair&);
//      my_IdPair& operator=(const my_IdPair&);
//
//    public:
//      // CREATORS
//      my_IdPair(const char       *id,
//                const char       *alias,
//                bslma::Allocator *basicAllocator = 0);
//          // Create an Id pair having the specified 'id' and 'alias' ids.
//          // Optionally specify a 'basicAllocator' used to supply memory.  If
//          // 'basicAllocator' is 0, the currently installed default allocator
//          // is used.
//
//      ~my_IdPair();
//          // Destroy this Id pair.
//
//      // ACCESSORS
//      const char *id() const;
//          // Return the primary id of this Id pair.
//
//      const char *alias() const;
//          // Return the alias of this Id pair.
//  };
//
//  // CREATORS
//  inline
//  my_IdPair::my_IdPair(const char       *id,
//                       const char       *alias,
//                       bslma::Allocator *basicAllocator)
//  : d_id(id, bslma::Default::allocator(basicAllocator))
//  , d_alias(alias)  // drat! (forgot to pass along 'basicAllocator')
//  {
//  }
//
//  inline
//  my_IdPair::~my_IdPair()
//  {
//  }
//
//  // ACCESSORS
//  inline
//  const char *my_IdPair::id() const
//  {
//      return d_id.id();
//  }
//
//  inline
//  const char *my_IdPair::alias() const
//  {
//      return d_alias.id();
//  }
//..
// The definition of the 'my_IdPair' constructor above intentionally includes a
// common programming error: The allocator in use by the object is not passed
// to *all* data members that require it.  We will see shortly how this error
// is detected at runtime using the default allocator.
//
// Next, the default allocator is set and locked identically to what was done
// in usage example 1:
//..
//  static my_CountingAllocator defaultCountingAllocator;
//
//  int status =
//              bslma::Default::setDefaultAllocator(&defaultCountingAllocator);
//  assert(0 == status);
//  bslma::Default::lockDefaultAllocator();
//  assert(bslma::Default::defaultAllocator() == &defaultCountingAllocator);
//..
// Now we instantiate an object of type 'my_IdPair' without explicitly
// specifying an allocator.  As a result, the object uses the default
// allocator.  The assertions verify the expected changes in the state of the
// default allocator:
//..
//  assert(0 == defaultCountingAllocator.numBlocksInUse());
//  assert(0 == defaultCountingAllocator.numBlocksTotal());
//  {
//      my_IdPair idPair("A", "B");
//      assert(2 == defaultCountingAllocator.numBlocksInUse());
//      assert(2 == defaultCountingAllocator.numBlocksTotal());
//  }
//  assert(0 == defaultCountingAllocator.numBlocksInUse());
//  assert(2 == defaultCountingAllocator.numBlocksTotal());
//..
// Next we instantiate a second object of type 'my_IdPair', this time supplying
// it with a counting allocator object that is distinct from the default
// allocator.  The assertions in the following code fragment that are commented
// out indicate the *expected* states of the allocators (i.e., in a bug-free
// implementation of 'my_IdPair') after the object has been constructed and
// again after it has been destroyed.  However, due to the (intentional) bug in
// the constructor, the uncommented assertions reveal the *true* state of
// affairs:
//..
//  my_CountingAllocator objectCountingAllocator;
//  assert(0 == objectCountingAllocator.numBlocksInUse());
//  assert(0 == objectCountingAllocator.numBlocksTotal());
//  {
//      my_IdPair idPair("X", "Y", &objectCountingAllocator);
//      // assert(2 == objectCountingAllocator.numBlocksInUse());
//      // assert(2 == objectCountingAllocator.numBlocksTotal());
//      // assert(0 == defaultCountingAllocator.numBlocksInUse());
//      // assert(2 == defaultCountingAllocator.numBlocksTotal());
//      assert(1 == objectCountingAllocator.numBlocksInUse());
//      assert(1 == objectCountingAllocator.numBlocksTotal());
//      assert(1 == defaultCountingAllocator.numBlocksInUse());
//      assert(3 == defaultCountingAllocator.numBlocksTotal());
//  }
//  // assert(0 == objectCountingAllocator.numBlocksInUse());
//  // assert(2 == objectCountingAllocator.numBlocksTotal());
//  // assert(0 == defaultCountingAllocator.numBlocksInUse());
//  // assert(2 == defaultCountingAllocator.numBlocksTotal());
//  assert(0 == objectCountingAllocator.numBlocksInUse());
//  assert(1 == objectCountingAllocator.numBlocksTotal());
//  assert(0 == defaultCountingAllocator.numBlocksInUse());
//  assert(3 == defaultCountingAllocator.numBlocksTotal());
//..
// Note that, although not necessary in the case of the simple 'my_IdPair'
// class, the default allocator can be used (and typically *should* be used)
// within the body of a constructor, or any other member function, to allocate
// dynamic memory that is *temporarily* needed by the method (and, hence, not
// owned by the object after the method has returned).  Thus, the invariant
// that must hold immediately after a method of an object returns is that the
// value returned by 'defaultCountingAllocator.numBlocksInUse()' must be
// *identical* to what it was immediately prior to calling the method.  Of
// course, note that the above invariant pertains to cases in *single*-threaded
// programs where the object allocator in use by the object is *distinct* from
// the default allocator.  Also note that the value returned by
// 'defaultCountingAllocator.numBlocksTotal()' *can* differ across function
// invocations (i.e., even in correct code).
//
///Example 3: Basic Global Allocator Use
///- - - - - - - - - - - - - - - - - - -
// Next we define a simple singleton class, 'my_Singleton', that defaults to
// using the global allocator if one is not explicitly specified when the
// singleton object is initialized.  Toward that end, note that in contrast to
// 'my_Id', the constructor for 'my_Singleton' uses:
//..
//  bslma::Default::globalAllocator(basicAllocator)
//..
// in its member initializer:
//..
//  // my_singleton.h
//  class my_Singleton {
//      // This is a trivial singleton class solely intended to illustrate use
//      // of the global allocator.
//
//      // CLASS DATA
//      static my_Singleton *s_singleton_p;  // pointer to singleton object
//
//      // PRIVATE DATA
//      my_Id d_id;  // allocating
//
//      // NOT IMPLEMENTED
//      my_Singleton(const my_Singleton&  original,
//                   bslma::Allocator    *basicAllocator = 0);
//      my_Singleton& operator=(const my_Singleton& rhs);
//
//    private:
//      // PRIVATE CREATORS
//      explicit my_Singleton(const char       *id,
//                            bslma::Allocator *basicAllocator = 0);
//          // Create a singleton having the specified 'id'.  Optionally
//          // specify a 'basicAllocator' used to supply memory.  If
//          // 'basicAllocator' is 0, the currently installed global allocator
//          // is used.
//
//      ~my_Singleton();
//          // Destroy this singleton.
//
//    public:
//      // CLASS METHODS
//      static void initSingleton(const char       *id,
//                                bslma::Allocator *basicAllocator = 0);
//          // Initialize the singleton with the specified 'id'.  Optionally
//          // specify a 'basicAllocator' used to supply memory.  If
//          // 'basicAllocator' is 0, the currently installed global allocator
//          // is used.
//
//      static const my_Singleton& singleton();
//          // Return a reference to the non-modifiable singleton of this
//          // class.  The behavior is undefined unless the singleton has been
//          // initialized.
//
//      // ACCESSORS
//      const char *id() const;
//          // Return the id of this singleton.
//  };
//
//  // CLASS METHODS
//  inline
//  const my_Singleton& my_Singleton::singleton()
//  {
//      return *s_singleton_p;
//  }
//
//  // CREATORS
//  inline
//  my_Singleton::my_Singleton(const char *id,
//                             bslma::Allocator *basicAllocator)
//  : d_id(id, bslma::Default::globalAllocator(basicAllocator))
//  {
//  }
//
//  inline
//  my_Singleton::~my_Singleton()
//  {
//  }
//
//  // ACCESSORS
//  inline
//  const char *my_Singleton::id() const
//  {
//      return d_id.id();
//  }
//..
// The following completes the definition of 'my_Singleton' in the component
// '.cpp' file:
//..
//  // my_singleton.cpp
//  #include <my_singleton.h>
//  #include <bsls_alignedbuffer.h>
//
//  my_Singleton *my_Singleton::s_singleton_p;
//
//  // CLASS METHODS
//  void my_Singleton::initSingleton(const char       *id,
//                                   bslma::Allocator *basicAllocator)
//  {
//      static bsls::AlignedBuffer<sizeof(my_Singleton)> singleton;
//      s_singleton_p = new (singleton.buffer()) my_Singleton(id,
//                                                            basicAllocator);
//  }
//..
// In the following, the default and global allocators are set to distinct
// instances of 'my_CountingAllocator'.  Note that the default allocator is set
// and locked identically to what was done in the previous two usage examples:
//..
//  static my_CountingAllocator defaultCountingAllocator;
//
//  int status = bslma::Default::setDefaultAllocator(
//                                                  &defaultCountingAllocator);
//  assert(0 == status);
//  bslma::Default::lockDefaultAllocator();
//  assert(bslma::Default::defaultAllocator() == &defaultCountingAllocator);
//
//  static my_CountingAllocator globalCountingAllocator;
//
//  bslma::Default::setGlobalAllocator(&globalCountingAllocator);
//  assert(bslma::Default::globalAllocator() == &globalCountingAllocator);
//..
// Finally, we initialize the singleton object.  We explicitly specify the
// desired allocator in the call to 'initSingleton' to make our intentions as
// clear as possible.  Of course, because of the way the 'my_Singleton'
// constructor was written, the result would have been the same if no allocator
// had been specified.  As in previous examples, the states of the default and
// global allocators are asserted before and after initializing the singleton:
//..
//  assert(0 == defaultCountingAllocator.numBlocksInUse());
//  assert(0 == defaultCountingAllocator.numBlocksTotal());
//  assert(0 == globalCountingAllocator.numBlocksInUse());
//  assert(0 == globalCountingAllocator.numBlocksTotal());
//
//  my_Singleton::initSingleton("S", bslma::Default::globalAllocator());
//
//  assert(0 == defaultCountingAllocator.numBlocksInUse());
//  assert(0 == defaultCountingAllocator.numBlocksTotal());
//  assert(1 == globalCountingAllocator.numBlocksInUse());
//  assert(1 == globalCountingAllocator.numBlocksTotal());
//..

#include <bslscm_version.h>

#include <bsls_atomicoperations.h>

#include <bslma_newdeleteallocator.h>

namespace BloombergLP {

namespace bslma {

class Allocator;

                        // ==============
                        // struct Default
                        // ==============

struct Default {
    // This struct is a mechanism with global state, i.e., all state is held in
    // global variables and all functions are class methods.  The state
    // consists of two distinct parts that don't influence one another: the
    // default allocator and the global allocator.  All addresses are stored
    // without assuming ownership.
    //
    // The 'setDefaultAllocator' method will only modify the default allocator
    // prior to the default allocator being accessed (by either 'allocator',
    // 'defaultAllocator', or 'lockDefaultAllocator'). The global allocator may
    // be freely modified.
    //
    // Note that *only* the *owner* of 'main' (or in *testing*), where the
    // caller affirmatively takes responsibility for the behavior of all
    // clients of the global allocator, is intended to change the global
    // allocator.

  private:
    // CLASS DATA

                        // *** default allocator ***

    static bsls::AtomicOperations::AtomicTypes::Pointer
                                                   s_requestedDefaultAllocator;
        // The default allocator that is requested by the user and will be
        // installed as the default allocator on the first attempt to access
        // the default allocator (via 'allocator', 'defaultAllocator', or
        // 'lockDefaultAllocator').  This value is initialized to '0',
        // indicating the user hasn't made a choice yet.  In that case, when
        // needed, the new-delete allocator will be used.  This value can be
        // set (multiple times) by calling to 'setDefaultAllocator'.  Note that
        // once changed this variable will not become '0' again.

    static bsls::AtomicOperations::AtomicTypes::Pointer s_defaultAllocator;
        // The currently installed default allocator.  This variable must be
        // set only once, when the default allocator is first accessed (via
        // 'allocator', 'defaultAllocator', or 'lockDefaultAllocator') but may
        // be '0' before it is accessed unless *for* *testing* *only*
        // 'setDefaultAllocatorRaw' is used.

                        // *** global allocator ***

    static bsls::AtomicOperations::AtomicTypes::Pointer s_globalAllocator;
        // The address of the global allocator to use.

    // PRIVATE CLASS METHODS
    static Allocator *determineAndReturnDefaultAllocator();
        // Return the address of the default allocator and disable all
        // subsequent calls to the 'setDefaultAllocator' method.  If
        // 's_defaultAllocator' is 0 (meaning the default allocator has not yet
        // been accessed), set it to the last value supplied to
        // 'setDefaultAllocator' (stored in 's_requestedDefaultAllocator').  If
        // 's_requestedDefaultAllocator' is 0 (meaning 'setDefaultAllocator'
        // has not been called) set 's_defaultAllocator' and
        // 's_requestedDefaultAllocator' to be the new-delete allocator.  Note
        // that this operation performs the one and only assigment to
        // 's_defaultAllocator' (unless 'setDefaultllocatorRaw' is called).
        // Note also that this function has the same externally visible
        // behavior as 'defaultAllocator', but forms the (thread-safe)
        // "slow-path" for that function's implementation.

  public:
    // CLASS METHODS

                        // *** default allocator ***

    static int setDefaultAllocator(Allocator *basicAllocator);
        // Set the address of the default allocator to the specified
        // 'basicAllocator' unless calls to this method have been disabled.
        // Return 0 on success and a non-zero value otherwise.  This method
        // will fail if either 'defaultAllocator', 'lockDefaultAllocator', or
        // 'allocator' with argument 0 has been called previously in this
        // process.  The behavior is undefined unless 'basicAllocator' is the
        // address of an allocator with sufficient lifetime to satisfy all
        // allocation requests within this process, and unless there is only
        // one thread started within this process.  Note that this method is
        // intended for use *only* by the *owner* of 'main' (or for use in
        // *testing*) where the caller affirmatively takes responsibility for
        // the behavior of all clients of the default allocator, and should
        // *not* be used for any other purpose.

    static void setDefaultAllocatorRaw(Allocator *basicAllocator);
        // Unconditionally set the address of the default allocator to the
        // specified 'basicAllocator'.  The behavior is undefined unless
        // 'basicAllocator' is the address of an allocator with sufficient
        // lifetime to satisfy all allocation requests within this process, and
        // unless there is only one thread started within this process.  Note
        // that this method is intended for use *only* in *testing* where the
        // caller affirmatively takes responsibility for the behavior of all
        // clients of the default allocator, and should *not* be used for any
        // other purpose.

    static void lockDefaultAllocator();
        // Disable all subsequent calls to the 'setDefaultAllocator' method.
        // Subsequent calls to this method have no effect.  Note that
        // subsequent calls to the 'setDefaultAllocatorRaw' method are *not*
        // disabled by this method.

    static Allocator *defaultAllocator();
        // Return the address of the default allocator and disable all
        // subsequent calls to the 'setDefaultAllocator' method.  Note that
        // prior to the first call to 'setDefaultAllocator' or
        // 'setDefaultAllocatorRaw' methods, the address of the default
        // allocator is that of the 'NewDeleteAllocator' singleton.  Also note
        // that subsequent calls to 'setDefaultAllocatorRaw' method are *not*
        // disabled by this method.

    static Allocator *allocator(Allocator *basicAllocator = 0);
        // Return the allocator returned by 'defaultAllocator' and disable all
        // subsequent calls to the 'setDefaultAllocator' method if the
        // optionally-specified 'basicAllocator' is 0; return 'basicAllocator'
        // otherwise.

                        // *** global allocator ***

    static Allocator *globalAllocator(Allocator *basicAllocator = 0);
        // Return the address of the global allocator if the optionally-
        // specified 'basicAllocator' is 0, and 'basicAllocator' otherwise.
        // Note that prior to the first call to the 'setGlobalAllocator'
        // method, the address of the global allocator is that of the
        // 'NewDeleteAllocator' singleton.

    static Allocator *setGlobalAllocator(Allocator *basicAllocator);
        // Unconditionally set the address of the global allocator to the
        // specified 'basicAllocator', or to the address of the
        // 'NewDeleteAllocator' singleton if 'basicAllocator' is 0.  Return the
        // address of the global allocator in effect immediately before calling
        // this method.  The behavior is undefined unless 'basicAllocator' is 0
        // or is the address of an allocator with sufficient lifetime to
        // satisfy all global allocation requests within this process, and
        // unless there is only one thread started within this process.  Note
        // that prior to the first call to this method, the address of the
        // global allocator is that of the 'NewDeleteAllocator' singleton.
        // Also note that this method is intended for use *only* by the *owner*
        // of 'main' (or for use in *testing*) where the caller affirmatively
        // takes responsibility for the behavior of all clients of the global
        // allocator, and should *not* be used for any other purpose.
};

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

                        // --------------
                        // struct Default
                        // --------------

// CLASS METHODS

                        // *** default allocator ***

inline
void Default::lockDefaultAllocator()
{
    determineAndReturnDefaultAllocator();
}

inline
Allocator *Default::defaultAllocator()
{
    void *alloc = bsls::AtomicOperations::getPtrRelaxed(&s_defaultAllocator);
    return alloc ? static_cast<Allocator *>(alloc)
                 : determineAndReturnDefaultAllocator();
}

inline
Allocator *Default::allocator(Allocator *basicAllocator)
{
    return basicAllocator ? basicAllocator : defaultAllocator();
}

                        // *** global allocator ***

inline
Allocator *Default::globalAllocator(Allocator *basicAllocator)
{
    Allocator *globalAllocator = static_cast<Allocator *>(const_cast<void *>(
                   bsls::AtomicOperations::getPtrAcquire(&s_globalAllocator)));

    return basicAllocator ? basicAllocator
                          : globalAllocator
                                      ? globalAllocator
                                      : &NewDeleteAllocator::singleton();
}

}  // close package namespace

#ifndef BDE_OPENSOURCE_PUBLICATION  // BACKWARD_COMPATIBILITY

// ============================================================================
//                           BACKWARD COMPATIBILITY
// ============================================================================

#ifndef BDE_OMIT_INTERNAL_DEPRECATED
                        // ====================
                        // struct bdema_Default
                        // ====================

typedef bslma::Default bdema_Default;
    // This 'struct' is a namespace for functions that manipulate and access
    // the default and global allocator pointers.  This alias is defined for
    // backward compatibility.

#endif // BDE_OMIT_INTERNAL_DEPRECATED

typedef bslma::Default bslma_Default;
    // This alias is defined for backward compatibility.

#endif  // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY

}  // 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 ----------------------------------