BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslma_deallocatorproctor.h
Go to the documentation of this file.
1/// @file bslma_deallocatorproctor.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslma_deallocatorproctor.h -*-C++-*-
8#ifndef INCLUDED_BSLMA_DEALLOCATORPROCTOR
9#define INCLUDED_BSLMA_DEALLOCATORPROCTOR
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslma_deallocatorproctor bslma_deallocatorproctor
15/// @brief Provide a proctor to conditionally manage a block memory.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslma
19/// @{
20/// @addtogroup bslma_deallocatorproctor
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslma_deallocatorproctor-purpose"> Purpose</a>
25/// * <a href="#bslma_deallocatorproctor-classes"> Classes </a>
26/// * <a href="#bslma_deallocatorproctor-description"> Description </a>
27/// * <a href="#bslma_deallocatorproctor-requirement"> Requirement </a>
28/// * <a href="#bslma_deallocatorproctor-usage"> Usage </a>
29///
30/// # Purpose {#bslma_deallocatorproctor-purpose}
31/// Provide a proctor to conditionally manage a block memory.
32///
33/// # Classes {#bslma_deallocatorproctor-classes}
34///
35/// - bslma::DeallocatorProctor: proctor to conditionally manage a memory
36///
37/// @deprecated Use bslma_deallocatebytesproctor instead
38///
39/// @see bslma_deallocatorguard, bslma_autodeallocator
40///
41/// # Description {#bslma_deallocatorproctor-description}
42/// This component provides a proctor class template,
43/// `bslma::DeallocatorProctor`, to conditionally manage a block of
44/// (otherwise-unmanaged) memory. If not explicitly released, the managed
45/// memory is deallocated automatically when the proctor object goes out of
46/// scope by freeing the memory using the parameterized `ALLOCATOR` (allocator
47/// or pool) supplied at construction. Note that after a proctor object
48/// releases its managed memory, the same proctor can be reused to conditionally
49/// manage another block of memory (allocated from the same allocator or pool
50/// that was supplied at construction) by invoking the `reset` method.
51///
52/// ## Requirement {#bslma_deallocatorproctor-requirement}
53///
54///
55/// The parameterized `ALLOCATOR` type of the `bslma::DeallocatorProctor` class
56/// must provide a (possibly `virtual`) method:
57/// @code
58/// void deallocate(void *address);
59/// @endcode
60/// to deallocate memory at the specified `address` (originally supplied by the
61/// `ALLOCATOR` object).
62///
63/// ## Usage {#bslma_deallocatorproctor-usage}
64///
65///
66/// The `bslma::DeallocatorProctor` is normally used to achieve *exception*
67/// *safety* in an *exception* *neutral* way by managing memory in a sequence of
68/// continuous memory allocations. Since each memory allocation may
69/// potentially throw an exception, an object of this proctor class can be used
70/// to (temporarily) manage newly allocated memory while attempting to allocate
71/// additional memory. Should an exception occur in subsequent memory
72/// allocation, the proctor's destructor deallocates its managed memory,
73/// preventing a memory leak.
74///
75/// This example illustrate a typical use of `bslma::DeallocatorProctor`.
76/// Suppose we have an array class that stores an "in-place" representation of
77/// objects of parameterized `TYPE`:
78/// @code
79/// // my_array.h
80/// // ...
81///
82/// /// This class implements an "in-place" array of objects of
83/// /// parameterized `TYPE` stored contiguously in memory.
84/// template <class TYPE>
85/// class my_Array {
86///
87/// // DATA
88/// TYPE *d_array_p; // dynamically allocated array
89/// int d_length; // logical length of this array
90/// int d_size; // physical capacity of this array
91/// bslma::Allocator *d_allocator_p; // allocator (held, not owned)
92///
93/// public:
94/// // CREATORS
95///
96/// /// Create a `my_Array` object. Optionally specify a
97/// /// `basicAllocator` used to supply memory. If `basicAllocator` is
98/// /// 0, the currently installed default allocator is used.
99/// my_Array(bslma::Allocator *basicAllocator = 0);
100///
101/// // ...
102///
103/// /// Destroy this `my_Array` object and all elements currently
104/// /// stored.
105/// ~my_Array();
106///
107/// // MANIPULATORS
108/// // ...
109///
110/// /// Append (a copy of) the specified `object` of parameterized
111/// /// `TYPE` to (the end of) this array.
112/// void append(const TYPE& object);
113///
114/// // ...
115/// };
116/// @endcode
117/// Note that the rest of the `my_Array` interface (above) and implementation
118/// (below) is elided as the portion shown is sufficient to demonstrate the use
119/// of `bslma::DeallocatorProctor`.
120/// @code
121/// // CREATORS
122/// template <class TYPE>
123/// inline
124/// my_Array<TYPE>::my_Array(bslma::Allocator *basicAllocator)
125/// : d_length(0)
126/// , d_size(1)
127/// , d_allocator_p(bslma::Default::allocator(basicAllocator))
128/// {
129/// d_array_p = (TYPE *)d_allocator_p->allocate(sizeof(TYPE));
130/// }
131///
132/// template <class TYPE>
133/// my_Array<TYPE>::~my_Array()
134/// {
135/// for (int i = 0; i < d_length; ++i) {
136/// d_array_p[i].~TYPE();
137/// }
138/// d_allocator_p->deallocate(d_array_p);
139/// }
140/// @endcode
141/// In order to implement the `append` function, we first have to introduce an
142/// `my_AutoDestructor` `class`, which automatically destroy a sequence of
143/// managed objects upon destruction. See `bslma::AutoDestructor` for a similar
144/// component with full documentation:
145/// @code
146/// // my_autodestructor.h
147/// // ...
148///
149/// /// This class implements a range proctor that, unless its `release`
150/// /// method has previously been invoked, automatically invokes the
151/// /// destructor of each of sequence of objects it manages.
152/// template <class TYPE>
153/// class my_AutoDestructor {
154///
155/// // DATA
156/// TYPE * d_origin_p;
157/// int d_length;
158///
159/// public:
160/// // CREATORS
161///
162/// /// Create an `my_AutoDestructor` to manage a contiguous sequence of
163/// /// objects.
164/// my_AutoDestructor(TYPE *origin, int length)
165/// : d_origin_p(origin)
166/// , d_length(length)
167/// {
168/// }
169///
170/// /// Destroy this `my_AutoDestructor` and, unless its `release`
171/// /// method has previously been invoked, destroy the sequence of
172/// /// objects it manages by invoking the destructor of each of the
173/// /// (managed) objects.
174/// ~my_AutoDestructor()
175/// {
176/// if (d_length) {
177/// for (; d_length > 0; --d_length, ++d_origin_p) {
178/// d_origin_p->~TYPE();
179/// }
180/// }
181/// }
182///
183/// // MANIPULATORS
184///
185/// /// Increase by one the length of the sequence of objects managed by
186/// /// this range proctor.
187/// my_AutoDestructor<TYPE>& operator++()
188/// {
189/// ++d_length;
190/// return *this;
191/// }
192///
193/// /// Release from management the sequence of objects currently
194/// /// managed by this range proctor.
195/// void release()
196/// {
197/// d_length = 0;
198/// }
199/// };
200/// @endcode
201/// We can now continue with our implementation of the `my_Array` class:
202/// @code
203/// // my_array.h
204/// // ...
205///
206/// // MANIPULATORS
207/// template <class TYPE>
208/// void my_Array<TYPE>::append(const TYPE &object)
209/// {
210/// if (d_length == d_size) {
211/// TYPE *newArray = (TYPE *)d_allocator_p->allocate(
212/// d_size * 2 * sizeof(TYPE)); // possibly throw
213///
214/// //*****************************************************************
215/// // Note the use of the deallocator proctor on 'newArray' (below). *
216/// //*****************************************************************
217///
218/// bslma::DeallocatorProctor<bslma::Allocator> proctor(newArray,
219/// d_allocator_p);
220///
221/// // Note use of 'my_AutoDestructor' here to protect the copy
222/// // construction of 'TYPE' objects.
223/// my_AutoDestructor<TYPE> destructor(newArray, 0);
224///
225/// for (int i = 0; i < d_length; ++i) {
226/// new(&newArray[i]) TYPE(d_array_p[i], d_allocator_p);
227/// // possibly throw
228/// d_array_p[i].~TYPE();
229/// ++destructor;
230/// }
231///
232/// destructor.release();
233///
234/// //*********************************************************
235/// // Note that the deallocator proctor is released (below). *
236/// //*********************************************************
237///
238/// proctor.release();
239///
240/// d_allocator_p->deallocate(d_array_p);
241/// d_array_p = newArray;
242/// d_size *= 2;
243/// }
244///
245/// new(&d_array_p[d_length]) TYPE(object, d_allocator_p);
246/// ++d_length;
247/// }
248/// @endcode
249/// Both the use of `bslma::DeallocatorProctor` and `my_AutoDestructor` are
250/// necessary to implement exception safety.
251///
252/// The `append` method defined above potentially throws in two places. If the
253/// memory allocator held in `d_allocator_p` where to throw while attempting to
254/// allocate the new array of parameterized `TYPE`, no memory would be leaked.
255/// But without subsequent use of the `bslma::DeallocatorProctor`, if the
256/// allocator subsequently throws while copy constructing the objects from the
257/// old array to the new array, the newly allocated memory block would be
258/// leaked. Using the `bslma::DeallocatorProctor` prevents the leak by
259/// deallocating the proctored memory automatically should the proctor go out
260/// of scope before the `release` method of the proctor is called (such as when
261/// the function exits prematurely due to an exception).
262///
263/// Similarly, any resources acquired as a result of copy constructing the
264/// objects from the old array to the new array would be leaked if the
265/// constructor of `TYPE` throws. Using the `my_AutoDestructor` prevents the
266/// leak by invoking the destructor of the proctored (and newly created) objects
267/// in the new array should the `my_AutoDestructor` goes out of scope before the
268/// `release` method of the proctor is called.
269///
270/// Note that the `append` method assumes the copy constructor of `TYPE` takes
271/// an allocator as a second argument. In production code, a constructor proxy
272/// that checks the traits of `TYPE` (to see whether `TYPE` uses
273/// `bslma::Allocator`) should be used (see `bslalg::ConstructorProxy`).
274/// @}
275/** @} */
276/** @} */
277
278/** @addtogroup bsl
279 * @{
280 */
281/** @addtogroup bslma
282 * @{
283 */
284/** @addtogroup bslma_deallocatorproctor
285 * @{
286 */
287
288#include <bslscm_version.h>
289
291
292#include <bsls_assert.h>
293
294
295
296namespace bslma {
297
298 // ========================
299 // class DeallocatorProctor
300 // ========================
301
302/// This class implements a proctor that, unless its `release` method has
303/// previously been invoked, automatically deallocates a block of managed
304/// memory upon destruction by invoking the `deallocate` method of an
305/// allocator (or pool) of parameterized `ALLOCATOR` type supplied to it at
306/// construction. The managed memory must have been provided by this
307/// allocator (or pool), which must remain valid throughout the lifetime of
308/// the proctor object.
309///
310/// See @ref bslma_deallocatorproctor
311template <class ALLOCATOR>
313
314 // DATA
316
317 // NOT IMPLEMENTED
319 DeallocatorProctor& operator=(const DeallocatorProctor&);
320
321 public:
322 // CREATORS
323
324 /// Create a deallocator proctor that conditionally manages the
325 /// specified `memory` (if non-zero), and that uses the specified
326 /// `allocator` to deallocate the block of memory managed by this
327 /// proctor (if not released -- see `release`) upon destruction. The
328 /// behavior is undefined unless `allocator` is non-zero and supplied
329 /// `memory`. Note that `allocator` must remain valid throughout the
330 /// lifetime of this proctor.
331 DeallocatorProctor(void *memory, ALLOCATOR *allocator);
332
333 /// Destroy this deallocator proctor, and deallocate the block of memory
334 /// it manages (if any) by invoking the `deallocate` method of the
335 /// allocator (or pool) that was supplied at construction of this
336 /// proctor. If no memory is currently being managed, this method has
337 /// no effect.
339
340 // MANIPULATORS
341
342 /// Release from management the block of memory currently managed by
343 /// this proctor. If no memory is currently being managed, this method
344 /// has no effect.
345 void release();
346
347 /// Set the specified `memory` as the block of memory to be managed by
348 /// this proctor. The behavior is undefined unless `memory` is non-zero
349 /// and was allocated by the allocator (or pool) supplied at
350 /// construction. Note that this method releases any previously-managed
351 /// memory from management (without deallocating it), and so may be
352 /// invoked with or without having called `release` when reusing this
353 /// object.
354 void reset(void *memory);
355};
356
357// ============================================================================
358// INLINE DEFINITIONS
359// ============================================================================
360
361 // ------------------------
362 // class DeallocatorProctor
363 // ------------------------
364
365// CREATORS
366template <class ALLOCATOR>
367inline
369 ALLOCATOR *allocator)
370 : d_imp(allocator, memory, 1)
371{
372 BSLS_ASSERT_SAFE(allocator);
373}
374
375template <class ALLOCATOR>
376inline
380
381// MANIPULATORS
382template <class ALLOCATOR>
383inline
385{
386 d_imp.release();
387}
388
389template <class ALLOCATOR>
390inline
392{
393 BSLS_ASSERT_SAFE(memory);
394
395 d_imp.reset(memory, 1);
396}
397
398} // close package namespace
399
400#ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY
401// ============================================================================
402// BACKWARD COMPATIBILITY
403// ============================================================================
404
405#ifdef bslma_DeallocatorProctor
406#undef bslma_DeallocatorProctor
407#endif
408/// This alias is defined for backward compatibility.
409#define bslma_DeallocatorProctor bslma::DeallocatorProctor
410#endif // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY
411
412
413
414#endif
415
416// ----------------------------------------------------------------------------
417// Copyright 2013 Bloomberg Finance L.P.
418//
419// Licensed under the Apache License, Version 2.0 (the "License");
420// you may not use this file except in compliance with the License.
421// You may obtain a copy of the License at
422//
423// http://www.apache.org/licenses/LICENSE-2.0
424//
425// Unless required by applicable law or agreed to in writing, software
426// distributed under the License is distributed on an "AS IS" BASIS,
427// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
428// See the License for the specific language governing permissions and
429// limitations under the License.
430// ----------------------------- END-OF-FILE ----------------------------------
431
432/** @} */
433/** @} */
434/** @} */
Definition bslma_deallocatebytesproctor.h:272
Definition bslma_deallocatorproctor.h:312
void release()
Definition bslma_deallocatorproctor.h:384
~DeallocatorProctor()
Definition bslma_deallocatorproctor.h:377
void reset(void *memory)
Definition bslma_deallocatorproctor.h:391
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1762
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition balxml_encoderoptions.h:68