BDE 4.14.0 Production release
|
Macros | |
#define | BDLMA_LOCAL_BUFFERED_VALUE_IS_ASSIGNABLE(DST, SRC) std::is_assignable<DST, SRC>::value |
Provide easy way to create an object with a local arena allocator.
This component provides a mechanism, LocalBufferedObject
, that contains a single instance of an allocator-aware object instantiated using an arena allocator that will allocate from "local" memory. This type is primarily used to simplify the creation of temporary objects utilizing a local memory buffer (typically on the stack) for efficiency, and is equivalent to creating a temporary object and supplying it a bdlma::LocalSequentialAllocator
. There are three template parameters – the type of object contained, the size in bytes of the buffer in the local arena allocator, and a bool
to indicate whether destruction of the contained object is to be disabled during emplace
and destruction of the mechansim. If the buffer used by the local arena allocator is exhausted, subsequent allocations come from the allocator passed at construction, or the default allocator if no allocator was passed at construction. Note that calls to deallocate
by the held object are ignored.
The container has 4 types of constructors:
1
above, but also passed an allocator.std::initializer_list
, propagated to the object.3
above, but also passed an allocator.If t_DISABLE_DESTRUCTOR
is set to true
, the LocalBufferedObject
, upon destruction or emplace
, will not destroy the contained object but will instead simply release any allocated memory. Eliding the contained objects destructor may improve efficiency, but is safe only if the contained object does not manage resources other than memory. I.e., it is unsafe to set t_DISABLE_DESTRUCTOR
to true
if the contained object manages resources other than memory (e.g., file handles, locks). By default t_DISABLE_DESTRUCTOR
is false
.
It is important that t_DISABLE_DESTRUCTION
be set to false
(the default) if any resources other than memory, such as file handles or mutexes, are managed by the held object.
The class
has two emplace
manipulators,
std::initializer_list
.Suppose we have an array of bsl::string_view
s containing names, with a large number of redundant entries, and we want to count how many unique names exist in the array. We write a function countUniqueNames
which stores the names in an unordered set, and yields the size
accessor as the total count of unique names.
The function will be called many times, and bsl::unordered_set
does a large number of small memory allocations. These allocations would be faster if they came from a non-freeing allocator that gets its memory from a buffer on the stack.
We can use a LocalBufferedObject
to create an unordered_set
with an 8192-byte stack buffer from which it is to allocate memory.
Notice that this syntactic convenience equivalent to supplying a local LocalSequentialAllocator
to the bsl::unordered_set
.
Below we show the allocation behavior of this function as the number of items in the unordered_set
increases. Note that when the memory in the 8192-byte stack buffer is exhausted, further memory comes from the default allocator:
Because the only resource managed by the unordered_set
is memory, we can improve the performance of the previous example using the template's boolean t_DISABLE_DESTRUCTOR
parameter.
unordered_set
allocates a lot of small nodes, and when the container is destroyed, unordered set's destructor traverses the whole data structure, visting every node and calling bslma::Allocator::deallocate
on each one, which is a non-inline virtual function call eventually handled by the sequential allocator's deallocate
function, which does nothing.
If we set the 3rd template parameter of LocalBufferedObject
, which is t_DISABLE_DESTRUCTION
of type bool
, to the non-default value of true
, the LocalBufferedObject
will not call the destructor of the held unordered_set
. This isn't a problem because unordered set manages no resource other than memory, and all the memory it uses is managed by the local sequential allocator contained in the local buffered object.
And we see the calculations are exactly the same:
#define BDLMA_LOCAL_BUFFERED_VALUE_IS_ASSIGNABLE | ( | DST, | |
SRC | |||
) | std::is_assignable<DST, SRC>::value |