BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlma_concurrentallocatoradapter.h
Go to the documentation of this file.
1/// @file bdlma_concurrentallocatoradapter.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlma_concurrentallocatoradapter.h -*-C++-*-
8#ifndef INCLUDED_BDLMA_CONCURRENTALLOCATORADAPTER
9#define INCLUDED_BDLMA_CONCURRENTALLOCATORADAPTER
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlma_concurrentallocatoradapter bdlma_concurrentallocatoradapter
15/// @brief Provide a thread-enabled adapter for the allocator protocol.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlma
19/// @{
20/// @addtogroup bdlma_concurrentallocatoradapter
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlma_concurrentallocatoradapter-purpose"> Purpose</a>
25/// * <a href="#bdlma_concurrentallocatoradapter-classes"> Classes </a>
26/// * <a href="#bdlma_concurrentallocatoradapter-description"> Description </a>
27/// * <a href="#bdlma_concurrentallocatoradapter-thread-safety"> Thread Safety </a>
28/// * <a href="#bdlma_concurrentallocatoradapter-usage"> Usage </a>
29/// * <a href="#bdlma_concurrentallocatoradapter-example-1-basic-usage"> Example 1: Basic Usage </a>
30///
31/// # Purpose {#bdlma_concurrentallocatoradapter-purpose}
32/// Provide a thread-enabled adapter for the allocator protocol.
33///
34/// # Classes {#bdlma_concurrentallocatoradapter-classes}
35///
36/// - bdlma::ConcurrentAllocatorAdapter: thread-enabled allocator adapter
37///
38/// @see bslma_allocator, bdlma_concurrentmultipool
39///
40/// # Description {#bdlma_concurrentallocatoradapter-description}
41/// This component provides an adapter,
42/// `bdlma::ConcurrentAllocatorAdapter`, that implements the `bslma::Allocator`
43/// protocol and provides synchronization for operations on an allocator
44/// supplied at construction using a mutex also supplied at construction.
45/// @code
46/// ,-----------------------------------.
47/// ( bdlma::ConcurrentAllocatorAdapter )
48/// `-----------------------------------'
49/// | ctor/dtor
50/// V
51/// ,-----------------.
52/// ( bslma::Allocator )
53/// `-----------------'
54/// allocate
55/// deallocate
56/// @endcode
57///
58/// ## Thread Safety {#bdlma_concurrentallocatoradapter-thread-safety}
59///
60///
61/// `bdlma::ConcurrentAllocatorAdapter` is *thread-enabled*, meaning any
62/// operation on the same instance can be safely invoked from any thread.
63///
64/// ## Usage {#bdlma_concurrentallocatoradapter-usage}
65///
66///
67/// This section illustrates intended use of this component.
68///
69/// ### Example 1: Basic Usage {#bdlma_concurrentallocatoradapter-example-1-basic-usage}
70///
71///
72/// In the following usage example, we develop a simple `AddressBook` class
73/// containing two thread-enabled vectors of strings: one for names, the other
74/// for addresses. We use a `bdlma::ConcurrentAllocatorAdapter` to synchronize
75/// memory allocations across our two thread-enabled vectors. For the purpose
76/// of this discussion, we first define a simple thread-enabled vector:
77/// @code
78/// /// This class defines a trivial thread-enabled vector.
79/// template <class TYPE>
80/// class ThreadEnabledVector {
81///
82/// // DATA
83/// mutable bslmt::Mutex d_mutex; // synchronize access
84/// bsl::vector<TYPE> d_elements; // underlying list of strings
85///
86/// private:
87/// // NOT IMPLEMENTED
88/// ThreadEnabledVector(const ThreadEnabledVector&);
89/// ThreadEnabledVector& operator=(const ThreadEnabledVector&);
90///
91/// public:
92/// // CREATORS
93///
94/// /// Create a thread-enabled vector. Optionally specify a
95/// /// `basicAllocator` used to supply memory. If `basicAllocator` is
96/// /// 0, the currently installed default allocator is used.
97/// ThreadEnabledVector(bslma::Allocator *basicAllocator = 0)
98/// : d_elements(basicAllocator)
99/// {
100/// }
101///
102/// /// Destroy this thread-enabled vector object.
103/// ~ThreadEnabledVector() {}
104///
105/// // MANIPULATORS
106///
107/// /// Append the specified `value` to this thread-enabled vector and
108/// /// return the index of the new element.
109/// int pushBack(const TYPE& value)
110/// {
111/// bslmt::LockGuard<bslmt::Mutex> guard(&d_mutex);
112/// d_elements.push_back(value);
113/// return static_cast<int>(d_elements.size()) - 1;
114/// }
115///
116/// /// Set the element at the specified `index` in this thread-enabled
117/// /// vector to the specified `value`. The behavior is undefined
118/// /// unless `0 <= index < length()`.
119/// void set(int index, const TYPE& value)
120/// {
121/// bslmt::LockGuard<bslmt::Mutex> guard(&d_mutex);
122/// d_elements[index] = value;
123/// }
124///
125/// // ACCESSORS
126///
127/// /// Return the value of the element at the specified `index` in this
128/// /// thread-enabled vector. Note that elements are returned *by*
129/// /// *value* because references to elements managed by this container
130/// /// may be invalidated by another thread.
131/// TYPE element(int index) const
132/// {
133/// bslmt::LockGuard<bslmt::Mutex> guard(&d_mutex);
134/// return d_elements[index];
135/// }
136///
137/// /// Return the number of elements in this thread-enabled vector.
138/// int length() const
139/// {
140/// bslmt::LockGuard<bslmt::Mutex> guard(&d_mutex);
141/// return static_cast<int>(d_elements.size());
142/// }
143/// };
144/// @endcode
145/// We use this thread-enabled vector to create a AddressBook class. However,
146/// we use the `bdlma::ConcurrentAllocatorAdapter` to prevent our two
147/// (thread-enabled) vectors from attempting synchronous memory allocations from
148/// our (potentially) non-thread safe `bslma::Allocator`. Note that we define a
149/// local class, `AddressBook_PrivateData`, in order to guarantee that
150/// `d_allocatorAdapter` and `d_mutex` are initialized before the thread-enabled
151/// vectors that depend on them:
152/// @code
153/// /// This `struct` contains a mutex and an allocator adapter. The
154/// /// `AddressBook` class will inherit from this structure, ensuring that
155/// /// the mutex and adapter are initialized before other member variables
156/// /// that depend on them.
157/// struct AddressBook_PrivateData {
158///
159/// private:
160/// // NOT IMPLEMENTED
161/// AddressBook_PrivateData(const AddressBook_PrivateData&);
162///
163/// public:
164/// bslmt::Mutex d_mutex; // synchronize allocator
165///
166/// bdlma::ConcurrentAllocatorAdapter
167/// d_allocatorAdapter; // adapter for allocator
168///
169/// /// Create a empty AddressBook private data object. Optionally
170/// /// specify a `basicAllocator` used to supply memory. If
171/// /// `basicAllocator` is 0, the currently installed default allocator
172/// /// is used.
173/// AddressBook_PrivateData(bslma::Allocator *basicAllocator = 0)
174/// : d_allocatorAdapter(&d_mutex, basicAllocator)
175/// {
176/// }
177/// };
178///
179/// /// This `class` defines a thread-enabled AddressBook containing vectors
180/// /// of names and addresses. Note that this class uses private
181/// /// inheritance to ensure that the allocator adapter and mutex are
182/// /// initialized before the vectors of names and addresses.
183/// class AddressBook : private AddressBook_PrivateData {
184///
185/// // DATA
186/// ThreadEnabledVector<bsl::string> d_names; // list of names
187/// ThreadEnabledVector<bsl::string> d_addresses; // list of addresses
188///
189/// private:
190/// // NOT IMPLEMENTED
191/// AddressBook(const AddressBook&);
192///
193/// public:
194/// // CREATORS
195///
196/// /// Create an empty AddressBook for storing names and addresses.
197/// /// Optionally specify a `basicAllocator` used to supply memory. If
198/// /// `basicAllocator` is 0, the currently installed default allocator
199/// /// is used.
200/// AddressBook(bslma::Allocator *basicAllocator = 0)
201/// : AddressBook_PrivateData(basicAllocator)
202/// , d_names(&d_allocatorAdapter)
203/// , d_addresses(&d_allocatorAdapter)
204/// {
205/// }
206///
207/// /// Destroy this AddressBook.
208/// ~AddressBook()
209/// {
210/// }
211///
212/// // MANIPULATORS
213///
214/// /// Add the specified `name` to this AddressBook and return the
215/// /// index of the newly-added name.
216/// int addName(const bsl::string& name)
217/// {
218/// return d_names.pushBack(name);
219/// }
220///
221/// /// Add the specified `address` to this AddressBook and return the
222/// /// index of the newly-added address.
223/// int addAddress(const bsl::string& address)
224/// {
225/// return d_addresses.pushBack(address);
226/// }
227///
228/// // ACCESSORS
229///
230/// /// Return the value of the name at the specified `index` in this
231/// /// AddressBook.
232/// bsl::string name(int index) const
233/// {
234/// return d_names.element(index);
235/// }
236///
237/// /// Return the value of the address at the specified `index` in this
238/// /// AddressBook.
239/// bsl::string address(int index) const
240/// {
241/// return d_addresses.element(index);
242/// }
243///
244/// /// Return the number of names in this AddressBook.
245/// int numNames() const
246/// {
247/// return d_names.length();
248/// }
249///
250/// /// Return the number of addresses in this AddressBook.
251/// int numAddresses() const
252/// {
253/// return d_addresses.length();
254/// }
255/// };
256/// @endcode
257/// @}
258/** @} */
259/** @} */
260
261/** @addtogroup bdl
262 * @{
263 */
264/** @addtogroup bdlma
265 * @{
266 */
267/** @addtogroup bdlma_concurrentallocatoradapter
268 * @{
269 */
270
271#include <bdlscm_version.h>
272
273#include <bslma_allocator.h>
274#include <bslma_default.h>
275
276#include <bslmt_mutex.h>
277
278#include <bsls_keyword.h>
279#include <bsls_types.h>
280
281#include <bslmt_mutex.h>
282
283
284namespace bdlma {
285
286 // ================================
287 // class ConcurrentAllocatorAdapter
288 // ================================
289
290/// This class defines an implementation of the `bslma::Allocator` protocol
291/// that "decorates" (wraps) a concrete `bslma::Allocator` to ensure
292/// thread-safe access to the decorated allocator.
293///
294/// See @ref bdlma_concurrentallocatoradapter
296
297 // DATA
298 bslmt::Mutex *d_mutex_p; // synchronizer for operations on the
299 // allocator (held, not owned)
300
301 bslma::Allocator *d_allocator_p; // allocator (held, not owned)
302
303 private:
304 // NOT IMPLEMENTED
307 public:
308 // CREATORS
309
310 /// Create a thread-enabled allocator adapter that uses the specified
311 /// `mutex` to synchronize access to the specified `basicAllocator`. If
312 /// `basicAllocator` is 0, the currently installed default allocator is
313 /// used.
315 bslma::Allocator *basicAllocator);
316
317 /// Destroy this thread-enabled allocator adapter.
319
320 // MANIPULATORS
321
322 /// Return a newly-allocated block of memory of (at least) the specified
323 /// `numBytes`. If `numBytes` is 0, a null pointer is returned with no
324 /// other effect. If this allocator cannot return the requested number
325 /// of bytes, then it will throw a `bsl::bad_alloc` exception in an
326 /// exception-enabled build, or else will abort the program in a non-exception build.
327 ///
328 /// \note Note that the alignment of the address
329 /// returned conforms to the platform requirement for any object of the
330 /// `numBytes`.
332
333 /// Return the memory at the specified `address` back to this allocator.
334 /// If `address` is 0, this function has no effect.
335 ///
336 /// \pre The behavior is undefined unless `address` was allocated using this allocator and
337 /// has not since been deallocated.
339};
340
341// ============================================================================
342// INLINE DEFINITIONS
343// ============================================================================
344
345 // --------------------------------
346 // class ConcurrentAllocatorAdapter
347 // --------------------------------
348
349// CREATORS
350inline
352 bslmt::Mutex *mutex,
353 bslma::Allocator *basicAllocator)
354: d_mutex_p(mutex)
355, d_allocator_p(bslma::Default::allocator(basicAllocator))
356{
357}
358
359} // close package namespace
360
361
362#endif
363
364// ----------------------------------------------------------------------------
365// Copyright 2016 Bloomberg Finance L.P.
366//
367// Licensed under the Apache License, Version 2.0 (the "License");
368// you may not use this file except in compliance with the License.
369// You may obtain a copy of the License at
370//
371// http://www.apache.org/licenses/LICENSE-2.0
372//
373// Unless required by applicable law or agreed to in writing, software
374// distributed under the License is distributed on an "AS IS" BASIS,
375// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
376// See the License for the specific language governing permissions and
377// limitations under the License.
378// ----------------------------- END-OF-FILE ----------------------------------
379
380/** @} */
381/** @} */
382/** @} */
Definition bdlma_concurrentallocatoradapter.h:295
~ConcurrentAllocatorAdapter() BSLS_KEYWORD_OVERRIDE
Destroy this thread-enabled allocator adapter.
void * allocate(bsls::Types::size_type numBytes) BSLS_KEYWORD_OVERRIDE
void deallocate(void *address) BSLS_KEYWORD_OVERRIDE
Definition bslma_allocator.h:545
std::size_t size_type
Definition bslma_allocator.h:593
Definition bslmt_mutex.h:317
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_OVERRIDE
Definition bsls_keyword.h:695
Definition bdlma_alignedallocator.h:278
Definition baljsn_encoder_testtypes.h:76
Definition bslmt_barrier.h:344
Definition bdlt_iso8601util.h:707