BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlma_concurrentallocatoradapter

Detailed Description

Provide a thread-enabled adapter for the allocator protocol.

Outline

Purpose

Provide a thread-enabled adapter for the allocator protocol.

Classes

See also
bslma_allocator, bdlma_concurrentmultipool

Description

This component provides an adapter, bdlma::ConcurrentAllocatorAdapter, that implements the bslma::Allocator protocol and provides synchronization for operations on an allocator supplied at construction using a mutex also supplied at construction.

,-----------------------------------.
`-----------------------------------'
| ctor/dtor
V
,-----------------.
( bslma::Allocator )
`-----------------'
allocate
deallocate
Definition bdlma_concurrentallocatoradapter.h:295

Thread Safety

bdlma::ConcurrentAllocatorAdapter is thread-enabled, meaning any operation on the same instance can be safely invoked from any thread.

Usage

This section illustrates intended use of this component.

Example 1: Basic Usage

In the following usage example, we develop a simple AddressBook class containing two thread-enabled vectors of strings: one for names, the other for addresses. We use a bdlma::ConcurrentAllocatorAdapter to synchronize memory allocations across our two thread-enabled vectors. For the purpose of this discussion, we first define a simple thread-enabled vector:

/// This class defines a trivial thread-enabled vector.
template <class TYPE>
class ThreadEnabledVector {
// DATA
mutable bslmt::Mutex d_mutex; // synchronize access
bsl::vector<TYPE> d_elements; // underlying list of strings
private:
// NOT IMPLEMENTED
ThreadEnabledVector(const ThreadEnabledVector&);
ThreadEnabledVector& operator=(const ThreadEnabledVector&);
public:
// CREATORS
/// Create a thread-enabled vector. Optionally specify a
/// `basicAllocator` used to supply memory. If `basicAllocator` is
/// 0, the currently installed default allocator is used.
ThreadEnabledVector(bslma::Allocator *basicAllocator = 0)
: d_elements(basicAllocator)
{
}
/// Destroy this thread-enabled vector object.
~ThreadEnabledVector() {}
// MANIPULATORS
/// Append the specified `value` to this thread-enabled vector and
/// return the index of the new element.
int pushBack(const TYPE& value)
{
d_elements.push_back(value);
return static_cast<int>(d_elements.size()) - 1;
}
/// Set the element at the specified `index` in this thread-enabled
/// vector to the specified `value`. The behavior is undefined
/// unless `0 <= index < length()`.
void set(int index, const TYPE& value)
{
d_elements[index] = value;
}
// ACCESSORS
/// Return the value of the element at the specified `index` in this
/// thread-enabled vector. Note that elements are returned *by*
/// *value* because references to elements managed by this container
/// may be invalidated by another thread.
TYPE element(int index) const
{
return d_elements[index];
}
/// Return the number of elements in this thread-enabled vector.
int length() const
{
return static_cast<int>(d_elements.size());
}
};
size_type size() const BSLS_KEYWORD_NOEXCEPT
Return the number of elements in this vector.
Definition bslstl_vector.h:3019
Definition bslstl_vector.h:1120
void push_back(const VALUE_TYPE &value)
Definition bslstl_vector.h:4343
Definition bslma_allocator.h:545
Definition bslmt_lockguard.h:234
Definition bslmt_mutex.h:317

We use this thread-enabled vector to create a AddressBook class. However, we use the bdlma::ConcurrentAllocatorAdapter to prevent our two (thread-enabled) vectors from attempting synchronous memory allocations from our (potentially) non-thread safe bslma::Allocator. Note that we define a local class, AddressBook_PrivateData, in order to guarantee that d_allocatorAdapter and d_mutex are initialized before the thread-enabled vectors that depend on them:

/// This `struct` contains a mutex and an allocator adapter. The
/// `AddressBook` class will inherit from this structure, ensuring that
/// the mutex and adapter are initialized before other member variables
/// that depend on them.
struct AddressBook_PrivateData {
private:
// NOT IMPLEMENTED
AddressBook_PrivateData(const AddressBook_PrivateData&);
public:
bslmt::Mutex d_mutex; // synchronize allocator
d_allocatorAdapter; // adapter for allocator
/// Create a empty AddressBook private data object. Optionally
/// specify a `basicAllocator` used to supply memory. If
/// `basicAllocator` is 0, the currently installed default allocator
/// is used.
AddressBook_PrivateData(bslma::Allocator *basicAllocator = 0)
: d_allocatorAdapter(&d_mutex, basicAllocator)
{
}
};
/// This `class` defines a thread-enabled AddressBook containing vectors
/// of names and addresses. Note that this class uses private
/// inheritance to ensure that the allocator adapter and mutex are
/// initialized before the vectors of names and addresses.
class AddressBook : private AddressBook_PrivateData {
// DATA
ThreadEnabledVector<bsl::string> d_names; // list of names
ThreadEnabledVector<bsl::string> d_addresses; // list of addresses
private:
// NOT IMPLEMENTED
AddressBook(const AddressBook&);
public:
// CREATORS
/// Create an empty AddressBook for storing names and addresses.
/// Optionally specify a `basicAllocator` used to supply memory. If
/// `basicAllocator` is 0, the currently installed default allocator
/// is used.
AddressBook(bslma::Allocator *basicAllocator = 0)
: AddressBook_PrivateData(basicAllocator)
, d_names(&d_allocatorAdapter)
, d_addresses(&d_allocatorAdapter)
{
}
/// Destroy this AddressBook.
~AddressBook()
{
}
// MANIPULATORS
/// Add the specified `name` to this AddressBook and return the
/// index of the newly-added name.
int addName(const bsl::string& name)
{
return d_names.pushBack(name);
}
/// Add the specified `address` to this AddressBook and return the
/// index of the newly-added address.
int addAddress(const bsl::string& address)
{
return d_addresses.pushBack(address);
}
// ACCESSORS
/// Return the value of the name at the specified `index` in this
/// AddressBook.
bsl::string name(int index) const
{
return d_names.element(index);
}
/// Return the value of the address at the specified `index` in this
/// AddressBook.
bsl::string address(int index) const
{
return d_addresses.element(index);
}
/// Return the number of names in this AddressBook.
int numNames() const
{
return d_names.length();
}
/// Return the number of addresses in this AddressBook.
int numAddresses() const
{
return d_addresses.length();
}
};
Definition bslstl_string.h:1252