BDE 4.14.0 Production release
|
Provide thread-safe memory-pooling allocator of fixed-size blocks.
This component defines a class, bdlma::ConcurrentPoolAllocator
, that implements the bslma::Allocator
protocol and provides a thread-safe allocator of pooled memory blocks of uniform size (the "pooled size"). The pooled size is either (1) configured at construction, or (2) equal to the size of the first block allocated through the allocator. All of the allocation requests of sizes up to the pooled size are satisfied with blocks from the underlying pool. All requests of sizes larger than the pooled size will be satisfied through the external allocator (the allocator supplied at construction, or the default allocator if no allocator was provided).
The interface hierarchy (defined by direct public inheritance) of bdlma::ConcurrentPoolAllocator
is as follows:
bdlma::ConcurrentPoolAllocator
provides a concrete, thread-safe implementation of the bslma::Allocator
protocol.
The bdlma::ConcurrentPoolAllocator
is intended to be used in either of the following two cases.
The first case is where frequent allocation and deallocation of memory occurs through the bslma::Allocator
protocol and all of the allocated blocks have the same size. In this case, the size of blocks to pool is determined the first time allocate
is called and need not be specified at construction.
The second case is where frequent allocation and deallocation of memory occurs through the bslma::Allocator
protocol, most of the allocations have similar sizes, and a likely maximum for the largest allocation is known at the time of construction.
The following example illustrates the use of bdlma::ConcurrentPoolAllocator
when all allocations are of uniform size. A bdlma::ConcurrentPoolAllocator
is used in the implementation of a "work
queue" where each "item" enqueued by a producer thread is of identical size. Concurrently, a consumer dequeues each work item when it becomes available, verifies the content (a sequence number in ASCII), and deallocates the work item. The concurrent allocations and deallocations are valid because bdlma::ConcurrentPoolAllocator
is thread-safe.
First, an abstract of the example will be given with focus and commentary on the relevant details of bdlma::ConcurrentPoolAllocator
. Details pertaining to queue management, thread creation, thread synchronization, etc., can be seen in the full listing at the end of this example.
The parent thread creates the bdlma::ConcurrentPoolAllocator
and work queue by the statements:
Note that since the default constructor is used to create poolAlloc
, the pooled size has not yet been fixed.
The work queue is defined by the following data structures.
The producer and consumer threads are given the address of the work queue as their sole argument. Here, the producer allocates a work item, initializes it with a sequence number in ASCII, enqueues it, and signals its presence to the consumer thread. This action is done 50 times, and then a 51st, empty work item is added to inform the consumer of the end of the queue. The first allocation of a work item (100 bytes) fixes the pooled size. Each subsequent allocation is that same size (100 bytes). The producer's actions are shown below:
When the consumer thread finds that the queue is not empty it dequeues the item, verifies its content (a sequence number in ASCII), returns the work item to the pool, and checks for the next item. If the queue is empty, the consumer blocks until signaled by the producer. An empty work item indicates that the producer will send no more items, so the consumer exits. The consumer's actions are shown below:
A complete listing of the example's structures and functions follows:
In the application main
:
The following example illustrates the use of bdlma::ConcurrentPoolAllocator
when allocations are of varying size. A bdlma::ConcurrentPoolAllocator
is used in the implementation of a "work
queue" where each "item" enqueued by a producer thread varies in size, but all items are smaller than a known maximum. Concurrently, a consumer thread dequeues each work item when it is available, verifies its content (a sequence number in ASCII), and deallocates the work item. The concurrent allocations and deallocations are valid because bdlma::ConcurrentPoolAllocator
is thread-safe.
First, an abstract of the example will be given with focus and commentary on the relevant details of bdlma::ConcurrentPoolAllocator
. Details pertaining to queue management, thread creation, thread synchronization, etc., can be seen in the full listing at the end of this example.
The parent thread creates the bdlma::ConcurrentPoolAllocator
and work queue by the statements:
Note that the pooled size (100) is specified in the construction of poolAlloc
. Any requests in excess of that size will be satisfied by implicit calls to the default allocator, not from the underlying pool.
The work queue is defined by the following data structures.
In this example (unlike Example 1), the given allocator is used not only for the work items, but is also passed to the constructor of d_queue
so that it also serves memory for the operations of bsl::list<my2_WorkItem>
.
The producer and consumer threads are given the address of the work queue as their sole argument. Here, the producer allocates a work item, initializes it with a sequence number in ASCII, enqueues it, and signals its presence to the consumer thread. The action is done 50 times, and then a 51st, empty work item is added to inform the consumer of the end of the queue. In this example, each work item is sized to match the length of its contents, the sequence number in ASCII. The producer's actions are shown below:
The actions of this consumer thread are essentially the same as those of the consumer thread in Example 1.
When the consumer thread finds that the queue is not empty, it dequeues the item, verifies its content (a sequence number in ASCII), returns the work item to the pool, and checks for the next item. If the queue is empty, the consumer blocks until signaled by the producer. An empty work item indicates that the producer will send no more items, so the consumer exits. The consumer's actions are shown below.
A complete listing of the example's structures and functions follows:
In the application's main
: