BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdlma_autoreleaser.h
Go to the documentation of this file.
1/// @file bdlma_autoreleaser.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlma_autoreleaser.h -*-C++-*-
8#ifndef INCLUDED_BDLMA_AUTORELEASER
9#define INCLUDED_BDLMA_AUTORELEASER
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlma_autoreleaser bdlma_autoreleaser
15/// @brief Release memory to a managed allocator or pool at destruction.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlma
19/// @{
20/// @addtogroup bdlma_autoreleaser
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlma_autoreleaser-purpose"> Purpose</a>
25/// * <a href="#bdlma_autoreleaser-classes"> Classes </a>
26/// * <a href="#bdlma_autoreleaser-description"> Description </a>
27/// * <a href="#bdlma_autoreleaser-requirements"> Requirements </a>
28/// * <a href="#bdlma_autoreleaser-usage"> Usage </a>
29/// * <a href="#bdlma_autoreleaser-example-1-using-a-bdlma-autoreleaser-to-preserve-exception-neutrality"> Example 1: Using a bdlma::AutoReleaser to Preserve Exception Neutrality </a>
30///
31/// # Purpose {#bdlma_autoreleaser-purpose}
32/// Release memory to a managed allocator or pool at destruction.
33///
34/// # Classes {#bdlma_autoreleaser-classes}
35///
36/// - bdlma::AutoReleaser: proctor to release memory to a managed allocator/pool
37///
38/// @see bslma_deallocatorproctor, bdlma_managedallocator
39///
40/// # Description {#bdlma_autoreleaser-description}
41/// This component provides a proctor object,
42/// `bdlma::AutoReleaser`, to manage memory allocated from a managed allocator
43/// or pool. The proctor's destructor invokes the `release` method of its
44/// managed allocator or pool unless the proctor's own `release` method has been
45/// called. Note that after a proctor releases management of its managed
46/// allocator or pool, the proctor can be reused by invoking its `reset` method
47/// with another allocator or pool object (of the same (template parameter) type
48/// `ALLOCATOR`).
49///
50/// ## Requirements {#bdlma_autoreleaser-requirements}
51///
52///
53/// The object of the (template parameter) type `ALLOCATOR` must provide a
54/// method having the following signature:
55/// @code
56/// void release();
57/// @endcode
58///
59/// ## Usage {#bdlma_autoreleaser-usage}
60///
61///
62/// This section illustrates intended use of this component.
63///
64/// ### Example 1: Using a bdlma::AutoReleaser to Preserve Exception Neutrality {#bdlma_autoreleaser-example-1-using-a-bdlma-autoreleaser-to-preserve-exception-neutrality}
65///
66///
67/// A `bdlma::AutoReleaser` proctor is often used to preserve exception
68/// neutrality for containers that allocate their elements using a managed
69/// allocator or pool. For operations that may potentially throw an exception,
70/// a proctor can be used to (temporarily) manage the container's allocator or
71/// pool and its associated memory. If an exception is thrown, the proctor's
72/// destructor invokes the `release` method of its held allocator or pool,
73/// deallocating memory for all of the container's elements, thereby preventing
74/// a memory leak and restoring the container to the empty state.
75///
76/// In this example, we illustrate use of a `bdlma::AutoReleaser` proctor within
77/// the `operator=` method of `my_FastStrArray`, a class that implements an
78/// array of C string elements. Note that a `my_FastStrArray` object allocates
79/// memory for its C string elements using a string pool, `my_StrPool`, the
80/// definition of which is elided.
81///
82/// First, we define the interface of our `my_FastStrArray` class:
83/// @code
84/// class my_FastCstrArray {
85/// // This class implements an array of C string elements. Each C string
86/// // is allocated using the 'my_StrPool' member for fast memory
87/// // allocation and deallocation.
88///
89/// // DATA
90/// char **d_array_p; // dynamically allocated array
91/// int d_capacity; // physical capacity of this array
92/// int d_length; // logical length of this array
93/// my_StrPool d_strPool; // memory manager to supply memory
94/// bslma::Allocator *d_allocator_p; // held, not owned
95///
96/// private:
97/// // PRIVATE MANIPULATORS
98/// void increaseSize();
99///
100/// // Not implemented:
101/// my_FastCstrArray(const my_FastCstrArray&);
102///
103/// public:
104/// // CREATORS
105/// my_FastCstrArray(bslma::Allocator *basicAllocator = 0);
106/// ~my_FastCstrArray();
107///
108/// // MANIPULATORS
109/// my_FastCstrArray& operator=(const my_FastCstrArray& rhs);
110/// void append(const char *item);
111///
112/// // ACCESSORS
113/// const char *operator[](int index) const { return d_array_p[index]; }
114/// int length() const { return d_length; }
115/// };
116///
117/// // FREE OPERATORS
118/// ostream& operator<<(ostream& stream, const my_FastCstrArray& array);
119///
120/// @endcode
121/// Then, we implement the methods:
122/// @code
123/// enum {
124/// k_MY_INITIAL_SIZE = 1, // initial physical capacity
125/// k_MY_GROW_FACTOR = 2 // factor by which to grow 'd_capacity'
126/// };
127///
128/// static inline
129/// int nextSize(int size)
130/// // Return the specified 'size' multiplied by 'k_MY_GROW_FACTOR'.
131/// {
132/// return size * k_MY_GROW_FACTOR;
133/// }
134///
135/// static inline
136/// void reallocate(char ***array,
137/// int *size,
138/// int newSize,
139/// int length,
140/// bslma::Allocator *allocator)
141/// // Reallocate memory in the specified 'array' and update the specified
142/// // 'size' to the specified 'newSize', using the specified 'allocator'
143/// // to supply memory. The specified 'length' number of leading elements
144/// // are preserved. If 'allocate' should throw an exception, this
145/// // function has no effect. The behavior is undefined unless
146/// // '1 <= newSize', '0 <= length', and 'length <= newSize'.
147/// {
148/// ASSERT(array);
149/// ASSERT(*array);
150/// ASSERT(size);
151/// ASSERT(1 <= newSize);
152/// ASSERT(0 <= length);
153/// ASSERT(length <= *size); // sanity check
154/// ASSERT(length <= newSize); // ensure class invariant
155///
156/// char **tmp = *array;
157///
158/// *array = (char **)allocator->allocate(newSize * sizeof **array);
159///
160/// // commit
161/// bsl::memcpy(*array, tmp, length * sizeof **array);
162/// *size = newSize;
163/// allocator->deallocate(tmp);
164/// }
165///
166/// void my_FastCstrArray::increaseSize()
167/// {
168/// reallocate(&d_array_p,
169/// &d_capacity,
170/// nextSize(d_capacity),
171/// d_length,
172/// d_allocator_p);
173/// }
174///
175/// // CREATORS
176/// my_FastCstrArray::my_FastCstrArray(bslma::Allocator *basicAllocator)
177/// : d_capacity(k_MY_INITIAL_SIZE)
178/// , d_length(0)
179/// , d_allocator_p(bslma::Default::allocator(basicAllocator))
180/// {
181/// d_array_p = (char **)d_allocator_p->allocate(
182/// d_capacity * sizeof *d_array_p);
183/// }
184///
185/// my_FastCstrArray::~my_FastCstrArray()
186/// {
187/// ASSERT(1 <= d_capacity);
188/// ASSERT(0 <= d_length);
189/// ASSERT(d_length <= d_capacity);
190///
191/// d_allocator_p->deallocate(d_array_p);
192/// }
193/// @endcode
194/// Now, we implement `my_FastCstrArray::operator=` using a
195/// `bdlma::AutoReleaser` proctor to preserve exception neutrality:
196/// @code
197/// // MANIPULATORS
198/// my_FastCstrArray&
199/// my_FastCstrArray::operator=(const my_FastCstrArray& rhs)
200/// {
201/// if (&rhs != this) {
202/// d_strPool.release();
203/// d_length = 0;
204///
205/// if (rhs.d_length > d_capacity) {
206/// char **tmp = d_array_p;
207/// d_array_p = (char **)d_allocator_p->allocate(
208/// rhs.d_length * sizeof *d_array_p);
209/// d_capacity = rhs.d_length;
210/// d_allocator_p->deallocate(tmp);
211/// }
212///
213/// bdlma::AutoReleaser<my_StrPool> autoReleaser(&d_strPool);
214///
215/// for (int i = 0; i < rhs.d_length; ++i) {
216/// const int size =
217/// static_cast<int>(bsl::strlen(rhs.d_array_p[i])) + 1;
218/// d_array_p[i] = (char *)d_strPool.allocate(size);
219/// bsl::memcpy(d_array_p[i], rhs.d_array_p[i], size);
220/// }
221///
222/// d_length = rhs.d_length;
223/// autoReleaser.release();
224/// }
225///
226/// return *this;
227/// }
228/// @endcode
229/// Note that a `bdlma::AutoReleaser` proctor is used to manage the array's C
230/// string memory pool while allocating memory for the individual elements. If
231/// an exception is thrown during the `for` loop, the proctor's destructor
232/// releases memory for all elements allocated through the pool, thus ensuring
233/// that no memory is leaked.
234///
235/// Finally, we complete the implementation:
236/// @code
237/// void my_FastCstrArray::append(const char *item)
238/// {
239/// if (d_length >= d_capacity) {
240/// this->increaseSize();
241/// }
242/// const int sSize = static_cast<int>(bsl::strlen(item)) + 1;
243/// char *elem = (char *)d_strPool.allocate(sSize);
244/// bsl::memcpy(elem, item, sSize * sizeof *item);
245/// d_array_p[d_length] = elem;
246/// ++d_length;
247/// }
248///
249/// // FREE OPERATORS
250/// ostream& operator<<(ostream& stream, const my_FastCstrArray& array)
251/// {
252/// stream << "[ ";
253/// for (int i = 0; i < array.length(); ++i) {
254/// stream << '"' << array[i] << "\" ";
255/// }
256/// return stream << ']' << flush;
257/// }
258/// @endcode
259/// @}
260/** @} */
261/** @} */
262
263/** @addtogroup bdl
264 * @{
265 */
266/** @addtogroup bdlma
267 * @{
268 */
269/** @addtogroup bdlma_autoreleaser
270 * @{
271 */
272
273#include <bdlscm_version.h>
274
275
276namespace bdlma {
277
278 // ==================
279 // class AutoReleaser
280 // ==================
281
282/// This class implements a proctor that invokes the `release` method of its
283/// managed allocator or pool at destruction unless the proctor's `release`
284/// method is invoked.
285///
286/// See @ref bdlma_autoreleaser
287template <class ALLOCATOR>
289
290 // DATA
291 ALLOCATOR *d_allocator_p; // allocator or pool (held, not owned)
292
293 private:
294 // NOT IMPLEMENTED
296 AutoReleaser& operator=(const AutoReleaser&);
297
298 public:
299 // CREATORS
300
301 /// Create a proctor object to manage the specified `originalAllocator`.
302 /// Unless the `release` method of this proctor is invoked, the
303 /// `release` method of `originalAllocator` is automatically invoked
304 /// upon destruction of this proctor.
305 AutoReleaser(ALLOCATOR *originalAllocator);
306
307 /// Destroy this proctor object and, unless the `release` method has
308 /// been invoked on this object with no subsequent call to `reset`,
309 /// invoke the `release` method of the held allocator or pool.
311
312 // MANIPULATORS
313
314 /// Release from management the allocator or pool currently managed by
315 /// this proctor. If no allocator or pool is currently being managed,
316 /// this method has no effect.
317 void release();
318
319 /// Set the specified `newAllocator` as the allocator or pool to be
320 /// managed by this proctor. Note that this method releases from
321 /// management any previously held allocator or pool, and so may be
322 /// invoked with or without having called `release` when reusing this
323 /// object.
324 void reset(ALLOCATOR *newAllocator);
325};
326
327// ============================================================================
328// INLINE DEFINITIONS
329// ============================================================================
330
331 // ------------------
332 // class AutoReleaser
333 // ------------------
334
335// CREATORS
336template <class ALLOCATOR>
337inline
338AutoReleaser<ALLOCATOR>::AutoReleaser(ALLOCATOR *originalAllocator)
339: d_allocator_p(originalAllocator)
340{
341}
342
343template <class ALLOCATOR>
344inline
346{
347 if (d_allocator_p) {
348 d_allocator_p->release();
349 }
350}
351
352// MANIPULATORS
353template <class ALLOCATOR>
354inline
356{
357 d_allocator_p = 0;
358}
359
360template <class ALLOCATOR>
361inline
362void AutoReleaser<ALLOCATOR>::reset(ALLOCATOR *newAllocator)
363{
364 d_allocator_p = newAllocator;
365}
366
367} // close package namespace
368
369
370#endif
371
372// ----------------------------------------------------------------------------
373// Copyright 2015 Bloomberg Finance L.P.
374//
375// Licensed under the Apache License, Version 2.0 (the "License");
376// you may not use this file except in compliance with the License.
377// You may obtain a copy of the License at
378//
379// http://www.apache.org/licenses/LICENSE-2.0
380//
381// Unless required by applicable law or agreed to in writing, software
382// distributed under the License is distributed on an "AS IS" BASIS,
383// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
384// See the License for the specific language governing permissions and
385// limitations under the License.
386// ----------------------------- END-OF-FILE ----------------------------------
387
388/** @} */
389/** @} */
390/** @} */
Definition bdlma_autoreleaser.h:288
void reset(ALLOCATOR *newAllocator)
Definition bdlma_autoreleaser.h:362
void release()
Definition bdlma_autoreleaser.h:355
~AutoReleaser()
Definition bdlma_autoreleaser.h:345
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdlma_alignedallocator.h:276