Quick Links: |
Provide allocators, guards, and other memory-management tools. More...
Components | |
Component bslma_allocator | |
Provide a pure abstract interface for memory-allocation mechanisms. | |
Component bslma_allocatoradaptor | |
Provide a polymorphic adaptor for STL-style allocators. | |
Component bslma_allocatortraits | |
Provide a uniform interface to standard allocator types. | |
Component bslma_allocatortraits_cpp03: PRIVATE | |
Provide C++03 implementation for bslma_allocatortraits.h. | |
Component bslma_autodeallocator | |
Provide a range proctor to managed a block of memory. | |
Component bslma_autodestructor | |
Provide a range proctor to manage an array of objects. | |
Component bslma_autorawdeleter | |
Provide a range proctor to manage a sequence objects. | |
Component bslma_bufferallocator: DEPRECATED | |
Support efficient memory allocations from a user-supplied buffer. | |
Component bslma_constructionutil | |
Provide methods to construct arbitrarily-typed objects uniformly. | |
Component bslma_constructionutil_cpp03: PRIVATE | |
Provide C++03 implementation for bslma_constructionutil.h. | |
Component bslma_deallocatorguard | |
Provide a guard to unconditionally manage a block of memory. | |
Component bslma_deallocatorproctor | |
Provide a proctor to conditionally manage a block memory. | |
Component bslma_default | |
Provide utilities to set/fetch the default and global allocators. | |
Component bslma_defaultallocatorguard | |
Provide scoped guard to temporarily change the default allocator. | |
Component bslma_deleterhelper | |
Provide namespace for functions used to delete objects. | |
Component bslma_destructionutil | |
Provide routines that destroy objects efficiently. | |
Component bslma_destructorguard | |
Provide a guard to unconditionally manage an object. | |
Component bslma_destructorproctor | |
Provide a proctor to conditionally manage an object. | |
Component bslma_exceptionguard | |
Provide a check that objects throwing exceptions do not change. | |
Component bslma_infrequentdeleteblocklist: DEPRECATED | |
Provide allocation and management of a sequence of memory blocks. | |
Component bslma_isstdallocator | |
Provide a compile-time check for determining allocator types. | |
Component bslma_mallocfreeallocator | |
Provide malloc/free adaptor to | |
Component bslma_managedallocator: DEPRECATED | |
Provide a protocol for memory allocators that support | |
Component bslma_managedptr | |
Provide a managed pointer class. | |
Component bslma_managedptr_cpp03: PRIVATE | |
Provide C++03 implementation for bslma_managedptr.h. | |
Component bslma_managedptr_factorydeleter: PRIVATE | |
Provide a factory-based deleter for the managed pointer class. | |
Component bslma_managedptr_members: PRIVATE | |
Provide the internal state of a managed pointer class. | |
Component bslma_managedptr_pairproxy: PRIVATE | |
Provide the internal state of a managed pointer class. | |
Component bslma_managedptrdeleter | |
Provide an in-core value-semantic class to call a delete function. | |
Component bslma_newdeleteallocator | |
Provide singleton new/delete adaptor to | |
Component bslma_rawdeleterguard | |
Provide a guard to unconditionally manage an object. | |
Component bslma_rawdeleterproctor | |
Provide a proctor to conditionally manage an object. | |
Component bslma_sequentialallocator: DEPRECATED | |
Support fast memory allocation for objects of varying sizes. | |
Component bslma_sequentialpool: DEPRECATED | |
Provide fast variable-size memory pool with allocation methods. | |
Component bslma_sharedptrinplacerep | |
Provide an in-place implementation of | |
Component bslma_sharedptrinplacerep_cpp03: PRIVATE | |
Provide C++03 implementation for bslma_sharedptrinplacerep.h. | |
Component bslma_sharedptroutofplacerep | |
Provide an out-of-place implementation of | |
Component bslma_sharedptrrep | |
Provide an abstract class for a shared object manager. | |
Component bslma_stdallocator | |
Provide an STL-compatible proxy for | |
Component bslma_stdallocator_cpp03: PRIVATE | |
Provide C++03 implementation for bslma_stdallocator.h. | |
Component bslma_stdtestallocator | |
Provide stl-compatible, | |
Component bslma_testallocator | |
Provide instrumented malloc/free allocator to track memory usage. | |
Component bslma_testallocatorexception | |
Provide an exception class for memory allocation operations. | |
Component bslma_testallocatormonitor | |
Provide a mechanism to summarize | |
Component bslma_usesbslmaallocator | |
Provide a metafunction to indicate the use of |
bslma_allocator
bslma_autodeallocator
bslma_autodestructor
bslma_autorawdeleter
bslma_deallocatorguard
bslma_deallocatorproctor
bslma_default
bslma_defaultallocatorguard
bslma_deleterhelper
bslma_destructorguard
bslma_destructorproctor
bslma_isstdallocator
bslma_mallocfreeallocator
bslma_newdeleteallocator
bslma_rawdeleterguard
bslma_rawdeleterproctor
bslma_testallocator
bslma_testallocatorexception
bslma_testallocatormonitor
Allocator
and ManagedAllocator
bslma
package provides an allocator protocol (i.e., a pure abstract interface) and a variety of concrete allocators derived from this protocol, as well as other memory-dispensing mechanisms and various guard constructs to prevent loss in case of exceptions. In addition, bslma
also provides a mechanism for installing a "default allocator" that will then be visible to all BDE and BDE-compliant code throughout that process. If this mechanism is not invoked explicitly, then an allocator that uses global new
and delete
is the BDE default allocator. This topic is discussed in more detail below. bslma
package currently has 45 components having 11 levels of physical dependency. The list below shows the hierarchical ordering of the components. The order of components within each level is not architecturally significant, just alphabetical. 11. bslma_isstdallocator 10. bslma_stdallocator 9. bslma_allocatortraits bslma_managedptr bslma_stdtestallocator 8. bslma_constructionutil bslma_managedptr_factorydeleter !PRIVATE! bslma_managedptr_members !PRIVATE! bslma_sequentialallocator !DEPRECATED! 7. bslma_autodeallocator bslma_autorawdeleter bslma_destructorproctor bslma_sequentialpool !DEPRECATED! bslma_sharedptrinplacerep bslma_sharedptroutofplacerep bslma_testallocatormonitor 6. bslma_allocatoradaptor bslma_autodestructor bslma_deallocatorguard bslma_deallocatorproctor bslma_defaultallocatorguard bslma_destructionutil bslma_destructorguard bslma_exceptionguard bslma_infrequentdeleteblocklist !DEPRECATED! bslma_managedptr_pairproxy !PRIVATE! bslma_managedptrdeleter bslma_rawdeleterguard bslma_rawdeleterproctor bslma_sharedptrrep 5. bslma_default bslma_testallocator 4. bslma_bufferallocator !DEPRECATED! bslma_mallocfreeallocator bslma_managedallocator !DEPRECATED! bslma_newdeleteallocator bslma_testallocatorexception bslma_usesbslmaallocator 3. bslma_allocator 2. bslma_allocatortraits_cpp03 !PRIVATE! bslma_deleterhelper 1. bslma_constructionutil_cpp03 !PRIVATE! bslma_managedptr_cpp03 !PRIVATE! bslma_sharedptrinplacerep_cpp03 !PRIVATE! bslma_stdallocator_cpp03 !PRIVATE!
bslma_allocator
: bslma_allocatoradaptor
: bslma_allocatortraits
: bslma_autodeallocator
: bslma_autodestructor
: bslma_autorawdeleter
: bslma_bufferallocator
: DEPRECATED bslma_constructionutil
: bslma_deallocatorguard
: bslma_deallocatorproctor
: bslma_default
: bslma_defaultallocatorguard
: bslma_deleterhelper
: bslma_destructionutil
: bslma_destructorguard
: bslma_destructorproctor
: bslma_exceptionguard
: bslma_infrequentdeleteblocklist
: DEPRECATED bslma_isstdallocator
: bslma_managedallocator
: DEPRECATED release
.bslma_managedptr
: bslma_managedptr_factorydeleter
: PRIVATE bslma_managedptr_members
: PRIVATE bslma_managedptr_pairproxy
: PRIVATE bslma_managedptrdeleter
: bslma_rawdeleterguard
: bslma_rawdeleterproctor
: bslma_sequentialallocator
: DEPRECATED bslma_sequentialpool
: DEPRECATED bslma_sharedptrinplacerep_cpp03
: PRIVATE bslma_sharedptrrep
: bslma_stdtestallocator
: bslma
-style allocator to track usage.bslma_testallocator
: bslma_testallocatorexception
: bslma_usesbslmaallocator
: bslma
allocators.bslma
package. See the documentation in each component for full details. bslma_allocator
component defines a protocol (i.e., an abstract base class) requiring the following interface: allocate
for memory allocation, and deallocate
, for allocation and deallocation of individual memory blocks. bslma_autodeallocator
component provides a range proctor class to manage a sequence of blocks of (otherwise-unmanaged) memory of a parameterized TYPE
supplied at construction. If not explicitly released, the sequence of managed memory blocks are deallocated automatically when the range proctor goes out of scope by freeing the memory using the parameterized ALLOCATOR
(allocator or pool) supplied at construction. This proctor mechanism is useful in guarding against memory leaks, e.g., when additional allocations may throw an exception. bslma_autodestructor
component provides a range proctor class to manage a sequence of blocks of (otherwise-unmanaged) memory of a parameterized TYPE
supplied at construction. If not explicitly released, the sequence of managed memory blocks are destroyed automatically when the range proctor goes out of scope by calling each (managed) object's destructor. This proctor mechanism is useful in guarding against memory leaks, e.g., when additional allocations may throw an exception. bslma_autorawdeleter
component provides a range proctor class template to manage a sequence of (otherwise-unmanaged) objects of parameterized TYPE
supplied at construction. If not explicitly released, the sequence of managed objects are deleted automatically when the range proctor goes out of scope by iterating over each object, first calling the (managed) object's destructor, and then freeing its memory footprint by invoking the deallocate
method of an allocator (or pool) of parameterized ALLOCATOR
type also supplied at construction. This proctor mechanism is useful in guarding against memory leaks, e.g., when additional allocations may throw an exception. bslma_deallocatorguard
component provides a guard class template to unconditionally manage a block of (otherwise-unmanaged) memory. The managed memory is deallocated automatically when the guard object goes out of scope using the deallocate
method of the parameterized ALLOCATOR
(allocator or pool) supplied at construction. This guard mechanism is useful in ensuring that a dynamically allocated raw memory resource is safely deallocated in the presense of multiple return satements or exceptions. bslma_deallocatorproctor
component provides a proctor class template to conditionally manage a block of (otherwise-unmanaged) memory. If not explicitly released, the managed memory is deallocated automatically when the proctor object goes out of scope by freeing the memory using the parameterized ALLOCATOR
(allocator or pool) supplied at construction. This proctor mechanism is useful in guarding against memory leaks, e.g., when additional allocations may throw an exception. bslma_default
component provides a namespace for a set of utility functions that manage the addresses of two static (global) memory allocator instances: the default allocator and the global allocator. The default allocator is the allocator used by default by all BDE components. The global allocator is the allocator used by default to construct global singleton objects. Each of these allocators are of type derived from bslma::Allocator
. bslma_defaultallocatorguard
component provides a mechanism that serves as a "scoped guard" to enable the temporary replacement of the process-wide default allocator. This functionality is intended for testing only, and in no event should this component be used except at the very beginning of main
. bslma_deleterhelper
component provides non-primitive procedures used to delete objects of parameterized TYPE
by first calling the destructor of the object, and then freeing the memory footprint of the object using a parameterized ALLOCATOR
(allocator or pool) provided as a second argument. bslma_destructorguard
component provides a guard class template to unconditionally manage an (otherwise-unmanaged) object of parameterized TYPE
supplied at construction. The managed object is destroyed automatically when the guard object goes out of scope by calling the (managed) object's destructor. This guard mechanism is useful in ensuring that a dynamically allocated raw memory resource is safely deallocated in the presense of multiple return satements or exceptions. bslma_destructorproctor
component provides a proctor class template to conditionally manage an (otherwise-unmanaged) object of parameterized TYPE
supplied at construction. If not explicitly released, the managed object is destroyed automatically when the proctor object goes out of scope by calling the object's destructor. This proctor mechanism is useful in guarding against memory leaks, e.g., when additional allocations may throw an exception. bslma_isstdallocator
component provides a meta-function, bsl::IsStdAllocator
, that determines if a type meets the requirements for an allocator, as specified in [container.requirements.general]. bslma_mallocfreeallocator
component provides a wrapper around std::malloc
and std::free
that adheres to the bslma::Allocator
protocol (i.e., provides allocate
and deallocate
functions). bslma_newdeleteallocator
component provides a wrapper around operator new
and operator delete
that adheres to the bslma::Allocator
protocol (i.e., provides an allocate
function and a deallocate
function). bslma_rawdeleterguard
component provides a guard class template to unconditionally manage an (otherwise-unmanaged) object of parameterized TYPE
supplied at construction. The managed object is deleted automatically when the guard object goes out of scope by first calling the (managed) object's destructor, and then freeing the memory using the parameterized ALLOCATOR
(allocator or pool) also supplied at construction. This guard mechanism is useful in ensuring that a dynamically allocated raw memory resource is safely deallocated in the presense of multiple return satements or exceptions. bslma_rawdeleterproctor
component provides a proctor class template to conditionally manage an (otherwise-unmanaged) object of parameterized TYPE
supplied at construction. If not explicitly released, the managed object is deleted automatically when the proctor object goes out of scope by first calling the (managed) object's destructor, and then freeing the memory using the parameterized ALLOCATOR
(allocator or pool) also supplied at construction. This proctor mechanism is useful in guarding against memory leaks, e.g., when additional allocations may throw an exception. bslma_testallocator
component provides an instrumented allocator that implements the bslma::Allocator
protocol and can be used to track various aspects of memory allocated from it. This allocator memory allocator uses global functions std::malloc
and std::free
for allocations and deallocations. bslma_testallocatorexception
component defines an exception object for use in testing exceptions during memory allocations. bslma_testallocatormonitor
component provides a "monitor", a mechanism class, that allows concise tests of state change (or lack of change) in the test allocator provided at the monitor's construction. std::allocator
) that use was rendered obsolete. But the standard also specified that all standard containers be parameterized on an allocator type that provides users greater control over the memory usage of individual objects and allows an application to control from where that memory comes (e.g., stack, heap, shared memory) and how it is distributed. By using allocators, an application can ensure efficient memory usage by reducing the number of distinct calls to global operators new
and delete
(and functions std::malloc
and std::free
). std::allocator
) provide users great control on how containers can allocate memory having a templated allocator argument introduces other problems. Two containers instantiated with different allocator types refer to different types making interoperability between them difficult and limiting the allocator type to a per-class (as opposed to a per-instance) basis. The standard's requirement of a templated allocator type is limited to containers and does not address other user-defined types that allocate memory. Although users can augment their types to take a templated allocator type such use is likely to be tedious and to result in significant object code increase. Finally, the standard is unclear with regards to the copy semantics of stateful allocators. bslma::Allocator
protocol and provides an allocate
method for obtaining memory, and a deallocate
method for returning memory (to the allocator). bslma
also provides many memory-dispensing mechanisms that also provide an allocate
and a deallocate
method, but these memory managers are not properly referred to as "allocators", since we reserve the term "allocator" for concrete memory dispensers that actually derive from bslma::Allocator
and are therefore usable anywhere that a bslma::Allocator *
is specified. Objects that dispense memory but that are not actually "allocators" are sometimes called "end-point allocators", and may offer performance advantages to certain users. Choosing an allocation mechanisms is complex, and many factors will influence the decision. The discussions here are aimed at shedding light on this important selection process. bslma
memory-allocation objects in general are: bslma::Allocator
. bslma
allocators are fully thread-safe but not thread-enabled (see the bsldoc_glossary
for terminology). bslma::Allocator
protocol. "End-point" allocators, such as a memory pool, are general-purpose mechanisms designed to minimize the runtime overhead of allocation and deallocation on a call-by-call basis and therefore do not derive from bslma::Allocator
. The bslma
package does not provide any end-point allocators although such implementations may be provided in higher-level libraries. bslma::Allocator
protocol) allows passing conformant allocators to BDE (and other) objects requiring an allocator at construction. Support of this common protocol also facilitates grouping the memory used by an object into one allocator. bslma
allocators is whether the allocator is a "managed" or "unmanaged" allocator. Unmanaged allocators, concrete implementations of bslma::Allocator
, require every allocation to be matched by a deallocation, similar to malloc
and free
, or new
and delete
. Managed allocators, concrete implementations of bslma::ManagedAllocator
, in addition to implementing the bslma::Allocator
protocol, provide simultaneous deallocation of all memory with one call to release
. This release
optimization can provide significant performance improvements if the only system resource held by an object (and all the objects it manages) is memory. The bslma
package does not provide any concrete managed allocator implementations although such implementations may be provided in higher-level libraries. bslma
package contains many components for managing dynamically-allocated objects. These components can be divided along two dimensions: bsldoc_glossary
for definitions of "proctor" and "guard". Proctors provide a mechanism to release the managed object, whereas, at least within bslma
, guards do not provide a release mechanism (and so are slightly more efficient on destruction if a release mechanism isn't needed). Deallocation Destruction Deletion +--------------------+-------------------+-------------------+ Proctor | DeallocatorProctor | DestructorProctor | RawDeleterProctor | +--------------------+-------------------+-------------------+ Guard | DeallocatorGuard | DestructorGuard | RawDeleterGuard | +--------------------+-------------------+-------------------+
bslma_rawdeleterproctor
and bslma_rawdeleterguard
) should be used only if we are sure that the supplied pointer is not of a type that is a secondary base class -- i.e., the (managed) object's address is (numerically) the same as when it was originally dispensed by ALLOCATOR
. bslma_autodeallocator
, bslma_autodestructor
and bslma_autorawdeleter
allow users to manage a sequence of objects or memory blocks. int
, a double
, or a pointer) whose size is not necessarily one byte. As a practical matter, for each entity separately, some alignments are "safe" and some are not. By "not safe" we mean that, for most platforms (e.g., all of our Unix machines), attempting to access an entity at an address that is not safely aligned for that entity will cause a bus error, crashing the program on the spot. In the very best case, the access will incur a performance penalty as the memory is shifted appropriately between its initial address and its target address (e.g., a register). new
(or malloc
, for C) automatically return memory blocks beginning at maximally-aligned addresses (the C++ standard requires it of new
). All memory managers in the bslma
package return maximally-aligned memory. bsls_alignment
|Alignment Strategy component for further information on the supported alignment strategies. deallocate
function is almost always provided, but in these managers it performs no action.) Such managers provide a release
function instead, which relinquishes all memory allocated by that manager since the previous release
call. All memory managers in the bslma
package deallocate the specified memory during a deallocate
method invocation. void *
) memory. bslma::NewDeleteAllocator
is hard-coded to obtain memory from the heap -- its underlying source is operator new
. bslma
package are compared in the following tables: PERFORMANCE CHARACTERISTICS Memory Source Allocation Alignment Out-of-memory Cost OVER Handling Underlying Source +-----------------+--------------+---------+--------------------+ NewDelete | 'operator new' | 0 if inlined,|MAXIMAL | Return value 0 | Allocator | |else vfn call+| | | +-----------------+--------------+---------+--------------------+ MallocFree | 'std::malloc' | 0 if inlined,|MAXIMAL | Return value 0 | Allocator | |else vfn call+| | | +-----------------+--------------+---------+--------------------+ Test | 'malloc' | N/A | None | Return value 0 | Allocator | | | | | +-----------------+--------------+---------+--------------------+ SEMANTICS Deallocation Storage Facility +-----------------------+-------------------------+ Newdelete | Single items only | Untyped, varying sizes | Allocator | | | +-----------------------+-------------------------+ MallocFree | Single items only | Untyped, varying sizes | Allocator | | | +-----------------------+-------------------------+ Test | Single items only | Untyped, varying sizes | Allocator | | | +-----------------------+-------------------------+
bslma::Allocator *
argument, which defaults to the value of bslma::Default::defaultAllocator()
. This value is set by BDE library code to be bslma::NewDeleteAllocator::singleton()
, but it can be changed: bslma::Default::setDefaultAllocator
sets the value of the (global) default allocator (although this is strongly discouraged), and bslma::Default::allocator
returns it. bslma::Allocator
object as an argument allows its clients to control how those objects allocate memory. An example of this is provided by showing the creators of a Customer
class
that stores the first and last names of a customer as bsl::string
objects and the various account numbers of that customer using a bsl::vector
. For simplicity part of the interface is elided. // ============== // class Customer // ============== class Customer { // This simply constrained (value-semantic) attribute class represents // the information about a bank's customer. A customer's first and last // name are represented as 'bsl::string' objects, the associated accounts // are stored in a 'bsl::vector<int>', and the employee identification // number is represented by an 'int'. Note that the class invariants are // identically the constraints on the individual attributes. // // This class: //: o supports a complete set of *value-semantic* operations //: o except for 'bslx' serialization //: o is *exception-neutral* (agnostic) //: o is *alias-safe* //: o is 'const' *thread-safe* // DATA bsl::string d_firstName; // first name bsl::string d_lastName; // last name bsl::vector<int> d_accounts; // account numbers int d_id; // customer identification number public:
bslma::Allocator
argument. // CREATORS Customer(bslma::Allocator *basicAllocator = 0); // Create a 'Customer' object having the (default) attribute values: //.. // firstName() == "" // lastName() == "" // accounts() == 0 // id() == 0 //.. // Optionally specify a 'basicAllocator' used to supply memory. If // 'basicAllocator' is 0, the currently installed default allocator // is used. Customer(const bslstl::StringRef& firstName, const bslstl::StringRef& lastName, const bsl::vector<int>& accounts, int id, bslma::Allocator *basicAllocator = 0); // Create a 'Customer' object having the specified 'firstName', // 'lastName', 'accounts', and 'id'' attribute values. Optionally // specify a 'basicAllocator' used to supply memory. If // 'basicAllocator' is 0, the currently installed default allocator // is used. Customer(const Customer& original, bslma::Allocator *basicAllocator = 0); // Create a 'Customer' object having the same value as the specified // 'original' object. Optionally specify a 'basicAllocator' used to // supply memory. If 'basicAllocator' is 0, the currently installed // default allocator is used. // Destroy this object. // Aspects bslma::Allocator *allocator() const; // Return the allocator used by this object to supply memory. Note // that if no allocator was supplied at construction the currently // installed default allocator is used. ... };
Customer
class
contains members that allocate memory it can associate the UsesBslmaAllocator
trait defined in the bslma
package to programmatically inform templated code that it uses an allocator. // TRAITS namespace BloombergLP{ namespace bslma { template <> struct UsesBslmaAllocator<Customer> : bsl::true_type {}; } } // ========================================================================== // INLINE FUNCTION DEFINITIONS // ========================================================================== // -------------- // class Customer // --------------
Customer
can simply forward the basicAllocator argument to its data members. All BSL containers, including bsl::string
and bsl::vector
, accept a bslma::Allocator
constructor argument: // CREATORS inline Customer::Customer(bslma::Allocator *basicAllocator) : d_firstName(basicAllocator) , d_lastName(basicAllocator) , d_accounts(basicAllocator) , d_id(0) { } inline Customer::Customer(const bslstl::StringRef& firstName, const bslstl::StringRef& lastName, const bsl::vector<int>& accounts, int id, bslma::Allocator *basicAllocator) : d_firstName(firstName.begin(), firstName.end(), basicAllocator) , d_lastName(lastName.begin(), lastName.end(), basicAllocator) , d_accounts(accounts, basicAllocator) , d_id(id) { BSLS_ASSERT_SAFE(!firstName.isEmpty()); BSLS_ASSERT_SAFE(!lastName.isEmpty()); } inline Customer::Customer(const Customer& original, bslma::Allocator *basicAllocator) : d_firstName(original.d_firstName, basicAllocator) , d_lastName(original.d_lastName, basicAllocator) , d_accounts(original.d_accounts, basicAllocator) , d_id(original.d_id) { } // MANIPULATORS inline Customer& Customer::operator=(const Customer& rhs) { d_firstName = rhs.d_firstName; d_lastName = rhs.d_lastName; d_accounts = rhs.d_accounts; d_id = rhs.d_id; return *this; } // Aspects inline bslma::Allocator *Customer::allocator() const { return d_firstName.get_allocator().mechanism(); }
class
: // ================ // class ObjectPool // ================ template <typename TYPE> class ObjectPool { // This 'class' provides a pool of reusable objects of the parameterized // 'TYPE' and assumes that the parameterized 'TYPE' provides a default // constructor, a destructor, and a 'reset' method. // DATA bsl::list<TYPE *> d_objects; // list of managed objects bslma::Allocator *d_allocator_p; // memory allocator (held, not owned) // PRIVATE CLASS METHODS TYPE *createObject(bsl::false_type); // Construct an object of the specified 'TYPE' that *does not* // require an allocator to be passed to its constructor. TYPE *createObject(bsl::true_type); // Construct an object of the specified 'TYPE' that *requires* an // allocator to be passed to its constructor. public: // CREATORS ObjectPool(bslma::Allocator *basicAllocator = 0); // Create an object pool that invokes the default constructor of the // parameterized 'TYPE' to construct objects. The optionally // specified 'basicAllocator' is used to supply memory. If // 'basicAllocator' is 0, the currently installed default allocator // is used. ~ObjectPool(); // Destroy this object pool. All objects created by this pool are // destroyed (even if some of them are still in use) and memory is // reclaimed. // MANIPULATORS TYPE* getObject(); // Return an address providing modifiable access to a // default-constructed object of the parameterized 'TYPE'. If this // pool does not have any free objects then a default-constructed // object is allocated and returned. void releaseObject(TYPE *object); // Return the specified 'object' back to this object pool. Invoke // the 'reset' method on 'object'. // The rest of the interface is elided for brevity. }; // ========================================================================== // INLINE FUNCTION DEFINITIONS // ========================================================================== // ---------------- // class ObjectPool // ----------------
createObject
private methods below allow an object to be created by specifying an allocator only if it has the UsesBslmaAllocator
trait. // PRIVATE CLASS METHODS template <typename TYPE> inline TYPE *ObjectPool<TYPE>::createObject(bsl::false_type) { return new (*d_allocator_p) TYPE(); } template <typename TYPE> inline TYPE *ObjectPool<TYPE>::createObject(bsl::true_type) { return new (*d_allocator_p) TYPE(d_allocator_p); } // CREATORS template <typename TYPE> inline ObjectPool<TYPE>::ObjectPool(bslma::Allocator *basicAllocator) : d_objects(basicAllocator) , d_allocator_p(bslma::Default::allocator(basicAllocator)) { } template <typename TYPE> ObjectPool<TYPE>::~ObjectPool() { for (bsl::list<TYPE *>::iterator iter = d_objects.begin(); iter != d_objects.end(); ++iter) { d_allocator_p->deleteObject(*iter); } d_objects.clear(); } // MANIPULATORS template <typename TYPE> TYPE *ObjectPool<TYPE>::getObject() { if (d_objects.size()) { TYPE *object = d_objects.back(); d_objects.pop_back(); return object; // RETURN } return createObject(bslma::UsesBslmaAllocator<TYPE>()); } template <typename TYPE> inline void ObjectPool<TYPE>::releaseObject(TYPE *object) { object->reset(); d_objects.push_back(object); }
bslma::Allocator
is a protocol, users can create their own concrete implementations for object-specific situations. A complete example of a concrete implementation that allocates memory from a user-supplied static buffer and reverts to an allocator specified at construction if that buffer is exhausted is provided below: // ===================== // class BufferAllocator // ===================== using namespace BloombergLP; class BufferAllocator : public bslma::Allocator { // This 'class' provides a concrete buffer allocator that implements the // 'bslma::Allocator' interface, allocating memory blocks from a // fixed-size buffer that is supplied by the user at construction, or // from an optionally-specified allocator once that buffer is exhausted. // DATA char *d_buffer_p; // buffer to use for memory // allocations (held, not owned) int d_bufferSize; // initial buffer size int d_cursor; // current cursor bslma::Allocator *d_allocator_p; // memory allocator to use once // 'd_buffer_p' is exhausted (held, // not owned) // NOT IMPLEMENTED BufferAllocator(const BufferAllocator&); BufferAllocator& operator=(const BufferAllocator&); public: // CREATORS BufferAllocator(char *buffer, int bufferSize, bslma::Allocator *basicAllocator = 0); // Create a buffer allocator for allocating memory blocks from the // specified 'buffer' of the specified 'bufferSize'. Optionally // specify a 'basicAllocator' used to supply memory after that // 'buffer' is exhausted. If 'basicAllocator' is 0, the currently // installed default allocator is used. virtual ~BufferAllocator(); // Destroy this buffer allocator. // MANIPULATORS virtual void *allocate(bsls_Types::size_type size); // Return the address of a contiguous block of maximally-aligned // memory of the specified 'size' (in bytes). If 'size' is 0 no // memory is allocated and 0 is returned. If the allocation request // exceeds the remaining free memory space in the external buffer // supplied at construction, the allocator specified at construction // is used. The behavior is undefined unless '0 <= size'. virtual void deallocate(void *address); // Deallocate the specified 'address' if it did not come from the // external buffer specified at construction and do nothing // otherwise. Note that if the buffer specified at construction was // not exhausted then no deallocation overhead is incurred. }; // ========================================================================== // INLINE FUNCTION DEFINITIONS // ========================================================================== // --------------------- // class BufferAllocator // --------------------- // CREATORS inline BufferAllocator::BufferAllocator(char *buffer, int bufferSize, bslma::Allocator *basicAllocator) : d_buffer_p(buffer) , d_bufferSize(bufferSize) , d_cursor(0) , d_allocator_p(bslma::Default::allocator(basicAllocator)) { } inline BufferAllocator::~BufferAllocator() { }
BufferAllocator
class
are provided below: // MANIPULATORS void *BufferAllocator::allocate(bsls_Types::size_type size) { BSLS_ASSERT_SAFE(0 <= size); // Calculate the appropriate aligned offset const int offset = bsls_AlignmentUtil::calculateAlignmentOffset( d_buffer_p + d_cursor, bsls::AlignmentUtil::BSLS_MAX_ALIGNMENT); if (d_cursor + offset + size > d_bufferSize) { return d_allocator_p->allocate(size); // RETURN } void *result = static_cast<void *>(&d_buffer_p[d_cursor + offset]); d_cursor += offset + size; return result; } void BufferAllocator::deallocate(void *address) { if (!(d_buffer_p <= address && address < d_buffer_p + d_bufferSize)) { d_allocator_p->deallocate(address); } }