Quick Links:

bal | bbl | bdl | bsl

Namespaces | Functions

Component bslma_allocatoradaptor
[Package bslma]

Provide a polymorphic adaptor for STL-style allocators. More...

Namespaces

namespace  bslma

Functions

 bslma::AllocatorAdaptor_Imp::AllocatorAdaptor_Imp ()
 bslma::AllocatorAdaptor_Imp::AllocatorAdaptor_Imp (const StlAllocatorType &stla)
virtual bslma::AllocatorAdaptor_Imp::~AllocatorAdaptor_Imp ()
virtual void * bslma::AllocatorAdaptor_Imp::allocate (size_type size)
virtual void bslma::AllocatorAdaptor_Imp::deallocate (void *address)
STL_ALLOC bslma::AllocatorAdaptor_Imp::adaptedAllocator () const
 bslma::AllocatorAdaptor::AllocatorAdaptor ()
 bslma::AllocatorAdaptor::AllocatorAdaptor (const STL_ALLOC &stla)

Detailed Description

Outline
Purpose:
Provide a polymorphic adaptor for STL-style allocators
Classes:
See also:
Description:
Within the BDE libraries, the prefered way to handle memory allocation is through a pointer to the polymorphic base class, bslma::Allocator. The use of a run-time polymorphism for the allocator has numerous advantages over the compile-time polymorphism used by the STL components. However, there are times when client code may have an STL-style allocator available and needs to use it with a BDE component.
This component provides a class template, AllocatorAdaptor that wraps the STL-style allocator in an object of class derived from bslma::Allocator. A pointer to the object can thus be used with any component that uses BDE-style memory allocation.
Usage:
Let's start with a simple class, my::FilePath, which allocates storage using a bslma::Allocator:
  #include <bslma_allocator.h>
  #include <bslma_default.h>
  #include <bsls_nullptr.h>

  #include <cstring>
  #include <cstdlib>

  namespace my {

  class FilePath {
      // Store the path of a file or directory
      bslma::Allocator *d_allocator;
      char             *d_data;

  public:
      FilePath(bslma::Allocator* basicAllocator = 0 /* nullptr */)
          : d_allocator(bslma::Default::allocator(basicAllocator))
          , d_data(0 /* nullptr */) { }

      FilePath(const char* s, bslma::Allocator* basicAllocator = 0)
          : d_allocator(bslma::Default::allocator(basicAllocator))
      {
          d_data =
               static_cast<char*>(d_allocator->allocate(std::strlen(s) + 1));
          std::strcpy(d_data, s);
      }

      bslma::Allocator *getAllocator() const { return d_allocator; }

      //...
  };

  } // close namespace my
Next, assume that an STL-allocator exists that uses memory exactly the way you need:
  template <class TYPE>
  class MagicAllocator {
      bool d_useMalloc;
  public:
      typedef TYPE        value_type;
      typedef TYPE       *pointer;
      typedef const TYPE *const_pointer;
      typedef unsigned    size_type;
      typedef int         difference_type;

      template <class U>
      struct rebind {
          typedef MagicAllocator<U> other;
      };

      explicit MagicAllocator(bool useMalloc = false)
          : d_useMalloc(useMalloc) { }

      template <class U>
      MagicAllocator(const MagicAllocator<U>& other)
          : d_useMalloc(other.getUseMalloc()) { }

      value_type *allocate(std::size_t n, void* = 0 /* nullptr */) {
          if (d_useMalloc)
              return (value_type*) std::malloc(n * sizeof(value_type));
          else
              return (value_type*) ::operator new(n * sizeof(value_type));
      }

      void deallocate(value_type *p, std::size_t) {
          if (d_useMalloc)
              std::free(p);
          else
              ::operator delete(p);
      }

      static size_type max_size() { return UINT_MAX / sizeof(TYPE); }

      void construct(pointer p, const TYPE& value)
          { new((void *)p) TYPE(value); }

      void destroy(pointer p) { p->~TYPE(); }

      int getUseMalloc() const { return d_useMalloc; }
  };

  template <class T, class U>
  inline
  bool operator==(const MagicAllocator<T>& a, const MagicAllocator<U>& b)
  {
      return a.getUseMalloc() == b.getUseMalloc();
  }

  template <class T, class U>
  inline
  bool operator!=(const MagicAllocator<T>& a, const MagicAllocator<U>& b)
  {
      return a.getUseMalloc() != b.getUseMalloc();
  }
Now, if we want to create a FilePath using a MagicAllocator, we need to adapt the MagicAllocator to the bslma::Allocator protocol. This is where bslma::AllocatorAdaptor comes in:
  int main()
  {
      MagicAllocator<char> ma(true);
      bslma::AllocatorAdaptor<MagicAllocator<char> >::Type maa(ma);

      my::FilePath usrbin("/usr/local/bin", &maa);

      assert(&maa == usrbin.getAllocator());
      assert(ma == maa.adaptedAllocator());

      return 0;
  }

Function Documentation

template<class STL_ALLOC >
bslma::AllocatorAdaptor_Imp< STL_ALLOC >::AllocatorAdaptor_Imp (  )  [inline, inherited]

= default

template<class STL_ALLOC >
bslma::AllocatorAdaptor_Imp< STL_ALLOC >::AllocatorAdaptor_Imp ( const StlAllocatorType stla  )  [inline, inherited]

Construct a polymorphic wrapper around a copy of the specified stla STL-style allocator.

template<class STL_ALLOC >
bslma::AllocatorAdaptor_Imp< STL_ALLOC >::~AllocatorAdaptor_Imp (  )  [inline, virtual, inherited]

Destroy this object and the STL-style allocator that it wraps.

template<class STL_ALLOC >
void * bslma::AllocatorAdaptor_Imp< STL_ALLOC >::allocate ( size_type  size  )  [virtual, inherited]

Return a maximally-aligned block of memory no smaller than size bytes allocated from the STL-style allocator that was supplied to this object's constructor. Any exceptions thrown by the underlying STL-style allocator are propagated out from this member.

Implements bslma::Allocator.

template<class STL_ALLOC >
void bslma::AllocatorAdaptor_Imp< STL_ALLOC >::deallocate ( void *  address  )  [virtual, inherited]

Return the memory block at the specified address back to the STL-allocator. If address is null, this funciton has no effect. The behavior is undefined unless address was allocated using this allocator object and has not already been deallocated.

Implements bslma::Allocator.

template<class STL_ALLOC >
STL_ALLOC bslma::AllocatorAdaptor_Imp< STL_ALLOC >::adaptedAllocator (  )  const [inherited]

Return a copy of the STL allocator stored within this object.

template<class STL_ALLOC >
bslma::AllocatorAdaptor< STL_ALLOC >::AllocatorAdaptor (  )  [inline, inherited]

= default

template<class STL_ALLOC >
bslma::AllocatorAdaptor< STL_ALLOC >::AllocatorAdaptor ( const STL_ALLOC &  stla  )  [inline, inherited]

Constructs a polymorphic wrapper around a copy of the specified stla STL-style allocator.