// bslma_sequentialallocator.h                                        -*-C++-*-
#ifndef INCLUDED_BSLMA_SEQUENTIALALLOCATOR
#define INCLUDED_BSLMA_SEQUENTIALALLOCATOR

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

//@PURPOSE: Support fast memory allocation for objects of varying sizes.
//
//@INTERNAL_DEPRECATED: Use 'bdlma_bufferedsequentialallocator' instead.
//
//@CLASSES:
//  bslma::SequentialAllocator: fast variable-size memory allocator
//
//@SEE_ALSO: bdlma_sequentialallocator, bdlma_bufferedsequentialallocator
//
//@DESCRIPTION: This component provides an allocator,
// 'bslma::SequentialAllocator', that implements the 'bslma::ManagedAllocator'
// protocol and allocates memory blocks of any requested size, from an internal
// buffer (pool) or a user-supplied buffer.  If an allocation request exceeds
// the remaining free memory space in the pool, the pool either 1) replenishes
// its buffer with new memory to satisfy the request, or 2) returns a separate
// memory block, depending on whether the request size exceeds an optionally
// specified maximum buffer size.  By default, buffer growth is not capped.
// The 'release' method releases all memory allocated through this allocator,
// as does the destructor.  Note, however, that individual allocated blocks of
// memory cannot be separately deallocated.
//..
//   ,--------------------------.
//  ( bslma::SequentialAllocator )
//   `--------------------------'
//                |         ctor/dtor
//                |         allocateAndExpand
//                |         expand
//                |         reserveCapacity
//                |         truncate
//                V
//    ,-----------------------.
//   ( bslma::ManagedAllocator )
//    `-----------------------'
//                |        release
//                V
//       ,-----------------.
//      (  bslma::Allocator )
//       `-----------------'
//                       allocate
//                       deallocate
//..
//
///Alignment Strategy
///------------------
// The 'bslma::SequentialPool' allocates memory using one of the two alignment
// strategies (defined in 'bslma_bufferallocator') optionally specified at
// construction: 1) MAXIMUM ALIGNMENT or 2) NATURAL ALIGNMENT.
//
//: 1 MAXIMUM ALIGNMENT: This strategy always allocates memory aligned with the
//:   most restrictive alignment on the host platform.  The value is defined by
//:   'bsls::AlignmentUtil::BSLS_MAX_ALIGNMENT'.
//:
//: 2 NATURAL ALIGNMENT: This strategy allocates memory whose alignment depends
//:   on the requested number of bytes.  An object of a fundamental type
//:   ('int', etc.) is *naturally* *aligned* when it's size evenly divides its
//:   address.  An object of an aggregate type has natural alignment if the
//:   alignment of the most-restrictively aligned sub-object evenly divides the
//:   address of the aggregate.  Natural alignment is always at least as
//:   restrictive as the compiler's required alignment.  When only the size of
//:   an aggregate is known, and not its composition, we compute the alignment
//:   by finding the largest integral power of 2 (up to and including
//:   'bsls::AlignmentUtil::BSLS_MAX_ALIGNMENT') that divides the requested
//:   (non-zero) number of bytes.  This computed alignment is guaranteed to be
//:   at least as restrictive as any sub-object within the aggregate.
//
// The default strategy is NATURAL ALIGNMENT.
//
///Optional 'buffer' Parameter
///---------------------------
// A buffer can be supplied to a 'bslma::SequentialAllocator' object at
// construction in which case the allocator will try to satisfy allocation
// requests using this buffer before switching to a dynamically-allocated
// internal pool.  Once the allocator is using an internal pool, it will not
// try to satisfy any subsequent allocation requests from the supplied buffer.
// Note that the allocator does *not* take ownership of the buffer.  Also note
// that 'bufferSize' may be specified using a positive or negative value to
// indicate a buffer growth strategy (see "Internal Buffer Growth").
//
///Optional 'initialSize' Parameter
///--------------------------------
// In lieu of an externally-supplied buffer, a value for the 'initialSize'
// parameter may be supplied at construction to specify the initial size of the
// internal pool.  If neither a buffer nor an 'initialSize' is specified, an
// implementation-defined value is used for an initial size of the internal
// pool.  Note that 'initialSize' may be specified using a positive or negative
// value to indicate a buffer growth strategy (see "Internal Buffer Growth").
//
///Internal Buffer Growth
///----------------------
// A 'bslma::SequentialAllocator' replenishes its internal buffer if the
// current buffer cannot satisfy an allocation request.  It does so by one of
// two growth strategies:
//
//: Constant Growth: The new buffer is always of the same size as the current
//:   buffer (possibly supplied at construction).
//:
//: Geometric Growth: The new buffer will be geometrically larger than the
//:   current buffer up to an optionally-specified maximum limit.
//
// If a 'bufferSize' (and corresponding 'buffer') or 'initialSize' is supplied
// at construction, the sign of its value implicitly specifies which growth
// strategy to use.  A positive value indicates Constant Growth, whereas a a
// negative value indicates Geometric Growth.  If neither 'bufferSize' nor
// 'initialSize' is supplied, Geometric Growth is used.  The optional
// 'maxBufferSize' parameter may be used to place a cap on Geometric Growth
// ('maxBufferSize' is ignored if Constant Growth is in effect).  If no value
// is specified for 'maxBufferSize', there is no cap on Geometric Growth.  Note
// that 'reserveCapacity' always ensures that the requested number of bytes is
// available (allocating a new internal pool if necessary) irrespective of
// whether the size of the request exceeds 'maxBufferSize'.
//
///Usage
///-----
// Allocators are often supplied to objects requiring dynamically-allocated
// memory at construction.  For example, consider the following
// 'my_DoubleStack' class, parameterized by a 'bslma::Allocator':
//..
//  // my_doublestack.h
//  // ...
//
//  namespace bslma { class Allocator; }
//
//  class my_DoubleStack {
//      // DATA
//      double           *d_stack_p;      // dynamically-allocated array
//      int               d_size;         // physical capacity this stack
//      int               d_length;       // next available index in stack
//      bslma::Allocator *d_allocator_p;  // memory allocator (held, not owned)
//
//      // FRIENDS
//      friend class my_DoubleStackIter;
//
//    private:
//      // PRIVATE MANIPULATORS
//      void increaseSize();
//          // Increase the capacity of this stack by at least one element.
//
//    public:
//      // CREATORS
//      my_DoubleStack(bslma::Allocator       *basicAllocator = 0);
//      my_DoubleStack(const my_DoubleStack&  original,
//                     bslma::Allocator       *basicAllocator = 0);
//      ~my_DoubleStack();
//
//      // MANIPULATORS
//      my_DoubleStack& operator=(const my_DoubleStack& rhs);
//      void push(double value);
//      void pop();
//
//      // ACCESSORS
//      const double& top() const;
//      bool isEmpty() const;
//  };
//
//  // ...
//
//  // MANIPULATORS
//  inline
//  void my_DoubleStack::push(double value)
//  {
//      if (d_length >= d_size) {
//          increaseSize();
//      }
//      d_stack_p[d_length++] = item;
//  }
//
//  // ...
//..
// The stack interface takes an optional 'basicAllocator' supplied only at
// construction.  (We avoid use of the name 'allocator' so as not to conflict
// with the STL use of the word, which differs slightly.)  If non-zero, the
// stack holds a pointer to this allocator, but does not own it.  If no
// allocator is supplied, the implementation itself must either conditionally
// invoke global 'new' and 'delete' explicitly whenever dynamic memory must be
// managed (BAD IDEA) or (GOOD IDEA) install a default allocator that adapts
// use of these global operators to the 'bslma_allocator' interface.  In actual
// practice, however, we might want the default to be run-time settable from a
// central location (see 'bslma_default').
//..
//  // my_doublestack.cpp
//  // ...
//  #include <my_doublestack.h>
//  #include <bslma_allocator.h>
//  #include <bslma_default.h>  // adapter for 'new' and 'delete'
//
//  enum { INITIAL_SIZE = 1, GROW_FACTOR = 2 };
//
//  // ...
//
//  // CREATORS
//  my_DoubleStack::my_DoubleStack(bslma::Allocator *basicAllocator)
//  : d_size(INITIAL_SIZE)
//  , d_length(0)
//  , d_allocator_p(basicAllocator)
//  {
//      assert(d_allocator_p);
//      d_stack_p = (double *)
//                  d_allocator_p->allocate(d_size * sizeof *d_stack_p);
//  }
//
//  my_DoubleStack::~my_DoubleStack()
//  {
//      // CLASS INVARIANTS
//      assert(d_allocator_p);
//      assert(d_stack_p);
//      assert(0 <= d_length);
//      assert(0 <= d_size);
//      assert(d_length <= d_size);
//
//      d_allocator_p->deallocate(d_stack_p);
//  }
//..
// Even in this simplified implementation, all use of the allocator protocol is
// relegated to the '.cpp' file.  Subsequent use of the allocator is
// demonstrated by the following file-scope static reallocation function:
//..
//  static
//  void reallocate(double **array, int newSize, int length,
//                  bslma::Allocator *basicAllocator)
//      // Reallocate memory in the specified 'array' to have the specified
//      // 'newSize' using the specified 'basicAllocator'.  The specified
//      // 'length' number of leading elements are preserved.  Given that the
//      // internal policy of class 'my_DoubleStack' requires that the physical
//      // capacity of the container may grow but never shrink, the behavior is
//      // undefined unless length <= newSize.
//  {
//      assert(array);
//      assert(1 <= newSize);
//      assert(0 <= length);
//      assert(basicAllocator);
//      assert(length <= newSize);        // enforce class invariant
//
//      double *tmp = *array;             // support exception neutrality
//      *array = (double *) basicAllocator->allocate(newSize * sizeof **array);
//
//      // COMMIT POINT
//
//      std::memcpy(*array, tmp, length * sizeof **array);
//      basicAllocator->deallocate(tmp);
//  }
//
//  void my_DoubleStack::increaseSize()
//  {
//      int proposedNewSize = d_size * GROW_FACTOR;     // reallocate can throw
//      assert(proposedNewSize > d_length);
//      reallocate(&d_stack_p, proposedNewSize, d_length, d_allocator_p);
//      d_size = proposedNewSize;                       // we're committed
//  }
//..

#ifdef BDE_OPENSOURCE_PUBLICATION // DEPRECATED
#error "bslma_sequentialallocator is deprecated"
#endif
#include <bslscm_version.h>

#include <bslma_bufferallocator.h>
#include <bslma_managedallocator.h>
#include <bslma_sequentialpool.h>

namespace BloombergLP {


namespace bslma {

class Allocator;

                       // =========================
                       // class SequentialAllocator
                       // =========================

class SequentialAllocator : public ManagedAllocator {
    // This class implements the 'ManagedAllocator' protocol to provide a fast
    // allocator of arbitrarily-sized blocks of memory.  Both the 'release'
    // method and the destructor atomically delete all memory managed by this
    // allocator; the 'deallocate' method, however, has no effect for this
    // class.

    // DATA
    SequentialPool d_sequentialPool;  // sequential pool mechanism

    // NOT IMPLEMENTED
    SequentialAllocator(const SequentialAllocator&);
    SequentialAllocator& operator=(const SequentialAllocator&);

  public:
    // CREATORS
    explicit SequentialAllocator(Allocator *basicAllocator = 0);
    explicit SequentialAllocator(
                       BufferAllocator::AlignmentStrategy  strategy,
                       Allocator                          *basicAllocator = 0);
    explicit SequentialAllocator(int        initialSize,
                                 Allocator *basicAllocator = 0);
    SequentialAllocator(
                       int                                 initialSize,
                       BufferAllocator::AlignmentStrategy  strategy,
                       Allocator                          *basicAllocator = 0);
        // Create a sequential allocator for allocating memory blocks from an
        // internal buffer.  Optionally specify an alignment 'strategy' used to
        // align allocated memory blocks.  If 'strategy' is not specified,
        // *Natural Alignment* is used.  Optionally specify an 'initialSize'
        // the absolute value of which indicates the initial size (in bytes)
        // for the internal buffer.  If 'initialSize' is not specified, an
        // implementation-defined value is used.  Optionally specify a
        // 'basicAllocator' used to supply memory.  If 'basicAllocator' is 0,
        // the currently installed default allocator is used.  If an 'allocate'
        // or 'reserveCapacity' request cannot be satisfied from the current
        // buffer, a new buffer is allocated, the size of which is determined
        // by a buffer growth strategy implied by 'initialSize'.  If
        // 'initialSize' was specified and is negative, or if it was *not*
        // specified, the buffer growth strategy used is *Geometric Growth*;
        // otherwise it is *Constant Growth*.  (See the component level
        // documentation for further details.)  In either case, the new buffer
        // will have sufficient capacity to satisfy the request.  If *Geometric
        // Growth* is in effect, no limit is imposed on the size of buffers.

    SequentialAllocator(char      *buffer,
                        int        bufferSize,
                        Allocator *basicAllocator = 0);
    SequentialAllocator(
                       char                               *buffer,
                       int                                 bufferSize,
                       BufferAllocator::AlignmentStrategy  strategy,
                       Allocator                          *basicAllocator = 0);
        // Create a sequential allocator for allocating memory blocks initially
        // from the specified 'buffer' the size (in bytes) of which is
        // indicated by the absolute value of the specified 'bufferSize'.
        // Optionally specify an alignment 'strategy' used to align allocated
        // memory blocks.  If 'strategy' is not specified, *Natural Alignment*
        // is used.  Optionally specify a 'basicAllocator' used to supply
        // memory.  If 'basicAllocator' is 0, the currently installed default
        // allocator is used.  If an 'allocate' or 'reserveCapacity' request
        // cannot be satisfied from the current buffer, a new buffer is
        // allocated, the size of which is determined by a buffer growth
        // strategy implied by 'bufferSize'.  If 'bufferSize' is negative, the
        // buffer growth strategy used is *Geometric Growth*; otherwise it is
        // *Constant Growth*.  (See the component level documentation for
        // further details.)  In either case, the new buffer will have
        // sufficient capacity to satisfy the request.  If *Geometric Growth*
        // is in effect, no limit is imposed on the size of buffers.

    SequentialAllocator(int        initialSize,
                        int        maxBufferSize,
                        Allocator *basicAllocator = 0);
    SequentialAllocator(
                       int                                 initialSize,
                       int                                 maxBufferSize,
                       BufferAllocator::AlignmentStrategy  strategy,
                       Allocator                          *basicAllocator = 0);
        // Create a sequential allocator for allocating memory blocks from an
        // internal buffer the initial size (in bytes) of which is indicated by
        // the absolute value of the specified 'initialSize'.  The specified
        // 'maxBufferSize' indicates the maximum size (in bytes) allowed for
        // internally allocated buffers.  Optionally specify an alignment
        // 'strategy' used to align allocated memory blocks.  If 'strategy' is
        // not specified, *Natural Alignment* is used.  Optionally specify a
        // 'basicAllocator' used to supply memory.  If 'basicAllocator' is 0,
        // the currently installed default allocator is used.  If an 'allocate'
        // or 'reserveCapacity' request cannot be satisfied from the current
        // buffer, a new buffer is allocated, the size of which is determined
        // by a buffer growth strategy implied by 'initialSize'.  If
        // 'initialSize' is negative, the buffer growth strategy used is
        // *Geometric Growth*; otherwise it is *Constant Growth*.  (See the
        // component level documentation for further details.)  In either case,
        // the new buffer will have sufficient capacity to satisfy the request.
        // If *Geometric Growth* is in effect, the geometric progression of
        // buffer sizes is capped at 'maxBufferSize'.  The behavior is
        // undefined unless '0 < maxBufferSize', and
        // '|initialSize| <= maxBufferSize'.  Note that 'maxBufferSize' is
        // ignored if 'initialSize > 0'.  Also note that 'maxBufferSize' may be
        // overridden by a sufficiently large value passed to 'allocate' or
        // 'reserveCapacity'.

    SequentialAllocator(char      *buffer,
                        int        bufferSize,
                        int        maxBufferSize,
                        Allocator *basicAllocator = 0);
    SequentialAllocator(
                       char                               *buffer,
                       int                                 bufferSize,
                       int                                 maxBufferSize,
                       BufferAllocator::AlignmentStrategy  strategy,
                       Allocator                          *basicAllocator = 0);
        // Create a sequential allocator for allocating memory blocks initially
        // from the specified 'buffer' the size (in bytes) of which is
        // indicated by the absolute value of the specified 'bufferSize'.  The
        // specified 'maxBufferSize' indicates the maximum size (in bytes)
        // allowed for internally allocated buffers.  Optionally specify an
        // alignment 'strategy' used to align allocated memory blocks.  If
        // 'strategy' is not specified, *Natural Alignment* is used.
        // Optionally specify a 'basicAllocator' used to supply memory.  If
        // 'basicAllocator' is 0, the currently installed default allocator is
        // used.  If an 'allocate' or 'reserveCapacity' request cannot be
        // satisfied from the current buffer, a new buffer is allocated, the
        // size of which is determined by a buffer growth strategy implied by
        // 'bufferSize'.  If 'bufferSize' is negative, the buffer growth
        // strategy used is *Geometric Growth*; otherwise it is *Constant
        // Growth*.  (See the component level documentation for further
        // details.)  In either case, the new buffer will have sufficient
        // capacity to satisfy the request.  If *Geometric Growth* is in
        // effect, the geometric progression of buffer sizes is capped at
        // 'maxBufferSize'.  The behavior is undefined unless
        // '0 < maxBufferSize', and '|bufferSize| <= maxBufferSize'.  Note that
        // 'maxBufferSize' is ignored if 'bufferSize > 0'.  Also note that
        // 'maxBufferSize' may be overridden by a sufficiently large value
        // passed to 'allocate' or 'reserveCapacity'.

    virtual ~SequentialAllocator();
        // Destroy this sequential allocator and release all associated memory.

    // MANIPULATORS
    virtual void *allocate(size_type numBytes);
        // 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.  The behavior is undefined unless '0 <= size'.  Note
        // that the alignment of the address returned is the maximum alignment
        // for any fundamental type defined for the calling platform.

    void *allocateAndExpand(int *size);
        // Return memory of at least the specified '*size' and return the
        // actual amount of memory allocated in '*size'.  If '*size' is 0, no
        // memory is allocated and 0 is returned.  The behavior is undefined
        // unless '0 <= *size'.

    void *allocateAndExpand(int *size, int maxNumBytes);
        // Return memory of at least the specified '*size' and at most the
        // specified 'maxNumBytes'.  Also return the actual amount of memory
        // allocated in '*size'.  If '*size' is 0, no memory is allocated and 0
        // is returned.  The behavior is undefined unless
        // '0 <= *size <= maxNumBytes'.

    virtual void deallocate(void *address);
        // This method has no effect for this allocator.

    int expand(void *address, int originalNumBytes);
        // Increase the amount of memory allocated at the specified 'address'
        // from the specified 'originalNumBytes' to the maximum amount easily
        // obtainable.  Return the amount of memory available at 'address'
        // after the expansion.  The behavior is undefined unless the call to
        // this allocator that provided the 'address' was performed with the
        // 'originalNumBytes'.  Note that this function will not expand the
        // memory unless there have been no allocations since the allocation
        // for 'originalNumBytes'.

    int expand(void *address, int originalNumBytes, int maxNumBytes);
        // Increase the amount of memory allocated at the specified 'address'
        // from the specified 'originalNumBytes' to the maximum amount easily
        // obtainable up to the specified 'maxNumBytes'.  Return the amount of
        // memory available at 'address' after the expansion.  The behavior is
        // undefined unless the call to this allocator that provided the
        // 'address' was performed with the 'originalNumBytes' and
        // 'originalNumBytes < maxNumBytes'.  Note that this function will not
        // expand the memory unless there have been no allocations since the
        // allocation for 'originalNumBytes'.

    virtual void release();
        // Release all memory currently allocated through this allocator.

    virtual void reserveCapacity(int numBytes);
        // Reserve sufficient memory to satisfy allocation requests for at
        // least the specified 'numBytes' without replenishment (i.e., without
        // internal allocation).  The behavior is undefined unless
        // '0 <= numBytes'.

    int truncate(void *address, int originalNumBytes, int newNumBytes);
        // Reduce the amount of memory allocated at the specified 'address'
        // from the specified 'originalNumBytes' to the specified
        // 'newNumBytes'.  Return the amount of memory available at 'address'
        // after the truncation.  The behavior is undefined unless the call to
        // this allocator that provided the 'address' was performed with the
        // 'originalNumBytes' and 'newNumBytes <= originalNumBytes'.  Note that
        // this function will not truncate the memory unless there have been no
        // allocations since the allocation for 'originalNumBytes'.
};

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

// CREATORS
inline
SequentialAllocator::SequentialAllocator(Allocator *basicAllocator)
: d_sequentialPool(basicAllocator)
{
}

inline
SequentialAllocator::SequentialAllocator(
                            BufferAllocator::AlignmentStrategy  strategy,
                            Allocator                          *basicAllocator)
: d_sequentialPool(strategy, basicAllocator)
{
}

inline
SequentialAllocator::SequentialAllocator(int        initialSize,
                                         Allocator *basicAllocator)
: d_sequentialPool(initialSize, basicAllocator)
{
}

inline
SequentialAllocator::SequentialAllocator(
                            int                                 initialSize,
                            BufferAllocator::AlignmentStrategy  strategy,
                            Allocator                          *basicAllocator)
: d_sequentialPool(initialSize, strategy, basicAllocator)
{
}

inline
SequentialAllocator::SequentialAllocator(char      *buffer,
                                         int        bufferSize,
                                         Allocator *basicAllocator)
: d_sequentialPool(buffer, bufferSize, basicAllocator)
{
}

inline
SequentialAllocator::SequentialAllocator(
                            char                               *buffer,
                            int                                 bufferSize,
                            BufferAllocator::AlignmentStrategy  strategy,
                            Allocator                          *basicAllocator)
: d_sequentialPool(buffer, bufferSize, strategy, basicAllocator)
{
}

inline
SequentialAllocator::SequentialAllocator(int        initialSize,
                                         int        maxBufferSize,
                                         Allocator *basicAllocator)
: d_sequentialPool(initialSize, maxBufferSize, basicAllocator)
{
}

inline
SequentialAllocator::SequentialAllocator(
                            int                                 initialSize,
                            int                                 maxBufferSize,
                            BufferAllocator::AlignmentStrategy  strategy,
                            Allocator                          *basicAllocator)
: d_sequentialPool(initialSize, maxBufferSize, strategy, basicAllocator)
{
}

inline
SequentialAllocator::SequentialAllocator(char      *buffer,
                                         int        bufferSize,
                                         int        maxBufferSize,
                                         Allocator *basicAllocator)
: d_sequentialPool(buffer, bufferSize, maxBufferSize, basicAllocator)
{
}

inline
SequentialAllocator::SequentialAllocator(
                            char                               *buffer,
                            int                                 bufferSize,
                            int                                 maxBufferSize,
                            BufferAllocator::AlignmentStrategy  strategy,
                            Allocator                          *basicAllocator)
: d_sequentialPool(buffer, bufferSize, maxBufferSize, strategy, basicAllocator)
{
}

// MANIPULATORS
inline
void *SequentialAllocator::allocate(size_type numBytes)
{
    return d_sequentialPool.allocate(static_cast<int>(numBytes));
}

inline
void *SequentialAllocator::allocateAndExpand(int *size)
{
    return d_sequentialPool.allocateAndExpand(size);
}

inline
void *SequentialAllocator::allocateAndExpand(int *size, int maxNumBytes)
{
    return d_sequentialPool.allocateAndExpand(size, maxNumBytes);
}

inline
void SequentialAllocator::deallocate(void *)
{
}

inline
int SequentialAllocator::expand(void *address, int originalNumBytes)
{
    return d_sequentialPool.expand(address, originalNumBytes);
}

inline
int SequentialAllocator::expand(void *address,
                                int   originalNumBytes,
                                int   maxNumBytes)
{
    return d_sequentialPool.expand(address, originalNumBytes, maxNumBytes);
}

inline
void SequentialAllocator::release()
{
    d_sequentialPool.release();
}

inline
void SequentialAllocator::reserveCapacity(int numBytes)
{
    d_sequentialPool.reserveCapacity(numBytes);
}

inline
int SequentialAllocator::truncate(void *address,
                                  int   originalNumBytes,
                                  int   newNumBytes)
{
    return d_sequentialPool.truncate(address, originalNumBytes, newNumBytes);
}

}  // close package namespace

#ifndef BDE_OPENSOURCE_PUBLICATION  // BACKWARD_COMPATIBILITY
// ============================================================================
//                           BACKWARD COMPATIBILITY
// ============================================================================

typedef bslma::SequentialAllocator bslma_SequentialAllocator;
    // 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 ----------------------------------