BDE 4.14.0 Production release
|
Provide a thread-safe pool of shared objects.
This component provides a generic thread-safe pool of shared objects, bdlcc::SharedObjectPool
, using the acquire-release idiom. The functionality provided is identical to bdlcc::ObjectPool
, except that getObject
returns efficiently-constructed bsl::shared_ptr
objects instead of raw pointers. For client code that needs to provide shared access to objects in the pool, this functionality saves an additional allocation for the shared pointer itself. Since the shared pointer and the object are contiguous in memory, this component also tends to improve performance by reducing "cache misses."
The object pool owns the memory required to store the pooled objects and the shared-pointer representations, and manages the construction, resetting, and destruction of objects. The user may supply functors to create objects and to reset them to a valid state for their return to the pool; alternatively, this component supplies reasonable defaults. Upon destruction the object pool deallocates all memory associated with the objects in the pool. The behavior is undefined if there are any outstanding shared pointer references to the objects in the pool when it is destroyed.
bdlcc::SharedObjectPool
is templated on two types CREATOR
and RESETTER
in addition to the underlying object TYPE
. Objects of these types may be provided at construction (or defaults may be used). The creator will be invoked as: void(*)(void*, bslma::Allocator*)
. The resetter will be invoked as: void(*)(TYPE*)
. The creator functor will be called to construct a new object of the parameterized TYPE
when the pool must be expanded (and thus it will typically invoke placement new and pass its allocator argument to the constructor of TYPE
). The resetter functor will be called before each object is returned to the pool, and is required to put the object into a state such that it is ready to be reused. The defaults for these types are as follows:
bdlcc::ObjectPoolFunctors::Nil
is a no-op; it is only suitable if the objects stored in the pool are always in a valid state to be reused. Otherwise - that is, if anything must be done to render the objects ready for reuse - another kind of RESETTER
should be provided (so long as that type supplies void(*)(TYPE*)
). In bdlcc::ObjectPoolFunctors
, the classes Clear
, RemoveAll
, and Reset
are all acceptable types for RESETTER
. Since these "functor" types are fully inline, it is generally most efficient to define reset()
(or clear()
or removeAll()
) in the underlying TYPE
and allow the functor to call that method. The CREATOR
functor defaults to an object that invokes the default constructor with placement new, passing the allocator argument if the type traits of the object indicate it uses an allocator (see bslma_usesbslmaallocator ). If a custom creator functor or a custom CREATOR
type is specified, it is the user's responsibility to ensure that it correctly passes its allocator argument through to the constructor of TYPE
if TYPE
uses allocator.
There are two potential sources of exceptions in this component: memory allocation and object construction. The object pool is exception-neutral with full guarantee of rollback for the following methods: if an exception is thrown in getObject
, reserveCapacity
, or increaseCapacity
, then the pool is in a valid unmodified state (i.e., identical to prior the call to getObject
). No other method of bdlcc::SharedObjectPool
can throw.
The growBy
parameter can be specified in the pool's constructor to instruct the pool how it is to increase its capacity each time the pool is depleted. If growBy
is positive, the pool always replenishes itself with enough objects so that it can satisfy at least growBy
object requests before the next replenishment. If growBy
is negative, the pool will increase its capacity geometrically until it exceeds the internal maximum (which itself is implementation-defined), and after that it will be replenished with constant number of objects. If growBy
is not specified, an implementation-defined default will be chosen. The behavior is undefined if growBy is 0.
This component is intended to improve the efficiency of code which provides shared pointers to pooled objects. As an example, consider a class which maintains a pool of vector<char>
objects and provides shared pointers to them. Using bdlcc::ObjectPool
, the class might be implemented like this:
Note that SlowCharArrayPool
must allocate the shared pointer itself from its d_spAllocator
in addition to allocating the charArray from its pool. Moreover, note that since the same function will handle resetting the object and returning it to the pool, we must define a special function for that purpose and bind its arguments.
We can solve both of these issues by using bdlcc::SharedObjectPool
instead:
Now the shared pointer and the object are allocated as one unit from the same allocator. In addition, the resetter method is a fully-inlined class that is only responsible for resetting the object, improving efficiency and simplifying the design. We can verify that use of bdlcc::SharedObjectPool
reduces the number of allocation requests: