BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslma_rawdeleterproctor.h
Go to the documentation of this file.
1/// @file bslma_rawdeleterproctor.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslma_rawdeleterproctor.h -*-C++-*-
8#ifndef INCLUDED_BSLMA_RAWDELETERPROCTOR
9#define INCLUDED_BSLMA_RAWDELETERPROCTOR
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslma_rawdeleterproctor bslma_rawdeleterproctor
15/// @brief Provide a proctor to conditionally manage an object.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslma
19/// @{
20/// @addtogroup bslma_rawdeleterproctor
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslma_rawdeleterproctor-purpose"> Purpose</a>
25/// * <a href="#bslma_rawdeleterproctor-classes"> Classes </a>
26/// * <a href="#bslma_rawdeleterproctor-description"> Description </a>
27/// * <a href="#bslma_rawdeleterproctor-raw-warning"> "Raw" Warning </a>
28/// * <a href="#bslma_rawdeleterproctor-requirement"> Requirement </a>
29/// * <a href="#bslma_rawdeleterproctor-usage"> Usage </a>
30///
31/// # Purpose {#bslma_rawdeleterproctor-purpose}
32/// Provide a proctor to conditionally manage an object.
33///
34/// # Classes {#bslma_rawdeleterproctor-classes}
35///
36/// - bslma::RawDeleterProctor: proctor to conditionally manage an object
37///
38/// @see bslma_rawdeleterguard, bslma_autorawdeleter
39///
40/// # Description {#bslma_rawdeleterproctor-description}
41/// This component provides a proctor class template,
42/// `bslma::RawDeleterProctor`, to conditionally manage an (otherwise-unmanaged)
43/// object of parameterized `TYPE` supplied at construction. If not explicitly
44/// released, the managed object is deleted automatically when the proctor
45/// object goes out of scope by first calling the (managed) object's destructor,
46/// and then freeing the memory using the parameterized `ALLOCATOR` (allocator
47/// or pool) also supplied at construction. Note that after a proctor object
48/// releases its managed object, the same proctor can be reused to conditionally
49/// manage another object (allocated from the same allocator or pool that was
50/// supplied at construction) by invoking the `reset` method.
51///
52/// ## "Raw" Warning {#bslma_rawdeleterproctor-raw-warning}
53///
54///
55/// Note that this component should be used only if we are sure that the
56/// supplied pointer is **not** of a type that is a secondary base class -- i.e.,
57/// the (managed) object's address is (numerically) the same as when it was
58/// originally dispensed by `ALLOCATOR`.
59///
60/// ## Requirement {#bslma_rawdeleterproctor-requirement}
61///
62///
63/// The parameterized `ALLOCATOR` type of the `bslma::RawDeleterProctor` class
64/// template must provide a (possibly `virtual`) method:
65/// @code
66/// void deallocate(void *address);
67/// @endcode
68/// to deallocate memory at the specified `address` (originally supplied by the
69/// `ALLOCATOR` object).
70///
71/// ## Usage {#bslma_rawdeleterproctor-usage}
72///
73///
74/// `bslma::RawDeleterProctor` is normally used to achieve *exception* *safety*
75/// in an *exception* *neutral* way by managing objects that are created
76/// temporarily on the heap, but not yet committed to a container object's
77/// management. This (somewhat contrived) example illustrates the use of a
78/// `bslma::RawDeleterProctor` to manage a dynamically-allocated object,
79/// deleting the object automatically should an exception occur.
80///
81/// Suppose we have a simple linked list class that manages objects of
82/// parameterized `TYPE`, but which are (for the purpose of this example)
83/// allocated separately from the links that hold them (thereby requiring two
84/// separate allocations for each `append` operation):
85/// @code
86/// // my_list.h
87/// // ...
88///
89/// template <class TYPE>
90/// class my_List {
91/// // This class is a container that uses a linked list data structure to
92/// // manage objects of parameterized 'TYPE'.
93///
94/// // PRIVATE TYPES
95/// struct Link {
96/// TYPE *d_object_p; // object held by the link
97/// Link *d_next_p; // next link
98/// };
99///
100/// // DATA
101/// Link *d_head_p; // head of list
102/// Link *d_tail_p; // tail of list
103/// int d_length; // number of objects
104/// bslma::Allocator *d_allocator_p; // allocator (held, not owned)
105///
106/// public:
107/// // CREATORS
108/// my_List(bslma::Allocator *basicAllocator = 0);
109/// // Create a 'my_List' object having an initial length of 0.
110/// // Optionally specify a 'basicAllocator' used to supply memory. If
111/// // 'basicAllocator' is 0, the currently installed default allocator
112/// // is used.
113///
114/// // ...
115///
116/// ~my_List();
117/// // Destroy this 'my_List' object and all elements currently stored.
118///
119/// // MANIPULATORS
120/// // ...
121///
122/// void append(const TYPE& object);
123/// // Append (a copy of) the specified 'object' of parameterized
124/// // 'TYPE' to (the end of) this list.
125///
126/// // ...
127/// };
128/// @endcode
129/// Note that the rest of the `my_List` interface (above) and implementation
130/// (below) are omitted as the portion shown is sufficient to demonstrate the
131/// use of `bslma::RawDeleterProctor`.
132/// @code
133/// // CREATORS
134/// template <class TYPE>
135/// inline
136/// my_List<TYPE>::my_List(bslma::Allocator *basicAllocator)
137/// : d_head_p(0)
138/// , d_tail_p(0)
139/// , d_length(0)
140/// , d_allocator_p(bslma::Default::allocator(basicAllocator))
141/// {
142/// }
143///
144/// template <class TYPE>
145/// my_List<TYPE>::~my_List()
146/// {
147/// while (d_head_p) {
148/// Link *tmp = d_head_p;
149/// d_head_p = d_head_p->d_next_p;
150/// d_allocator_p->deleteObject(tmp->d_object_p);
151/// d_allocator_p->deallocate(tmp);
152/// }
153/// }
154///
155/// // MANIPULATORS
156/// template <class TYPE>
157/// void my_List<TYPE>::append(const TYPE& object)
158/// {
159/// TYPE *tmp = (TYPE *)new(*d_allocator_p) TYPE(object, d_allocator_p);
160/// // possibly throw
161///
162/// //************************************************************
163/// // Note the use of the raw deleter proctor on 'tmp' (below). *
164/// //************************************************************
165///
166/// bslma::RawDeleterProctor<TYPE, bslma::Allocator> proctor(tmp,
167/// d_allocator_p);
168///
169/// if (!d_head_p) {
170/// d_head_p = new(*d_allocator_p) Link; // possibly throw
171/// d_tail_p = d_head_p;
172/// }
173/// else {
174/// d_tail_p->d_next_p = new(*d_allocator_p) Link; // possibly throw
175/// d_tail_p = d_tail_p->d_next_p;
176/// }
177/// d_tail_p->d_object_p = tmp;
178/// d_tail_p->d_next_p = 0;
179///
180/// //*********************************************************
181/// // Note that the raw deleter proctor is released (below). *
182/// //*********************************************************
183///
184/// proctor.release();
185/// }
186/// @endcode
187/// The `append` method defined above potentially throws in three places. If
188/// the memory allocator held in `d_allocator_p` were to throw while attempting
189/// to create the object of parameterized `TYPE`, no memory would be leaked.
190/// But without subsequent use of the `bslma::RawDeleterProctor`, if the
191/// allocator subsequently throws while creating the link, all memory (and any
192/// other resources) acquired as a result of copying the (not-yet-managed)
193/// object would be leaked. Using the `bslma::RawDeleterProctor` prevents the
194/// leaks by deleting the proctored object automatically should the proctor go
195/// out of scope before the `release` method of the proctor is called (such as
196/// when the function exits prematurely due to an exception).
197///
198/// Note that the `append` method assumes the copy constructor of `TYPE` takes
199/// an allocator as a second argument. In production code, a constructor proxy
200/// that checks the traits of `TYPE` (to determine whether `TYPE` uses
201/// `bslma::Allocator`) should be used (see @ref bslalg_constructorproxy ).
202/// @}
203/** @} */
204/** @} */
205
206/** @addtogroup bsl
207 * @{
208 */
209/** @addtogroup bslma
210 * @{
211 */
212/** @addtogroup bslma_rawdeleterproctor
213 * @{
214 */
215
216#include <bslscm_version.h>
217
218#include <bslma_deleterhelper.h>
219
220#include <bsls_assert.h>
221#include <bsls_performancehint.h>
222
223
224
225namespace bslma {
226
227 // =======================
228 // class RawDeleterProctor
229 // =======================
230
231/// This class implements a proctor that, unless its `release` method has
232/// previously been invoked, automatically deletes a managed object upon
233/// destruction by first invoking the object's destructor, and then invoking
234/// the `deallocate` method of an allocator (or pool) of parameterized
235/// `ALLOCATOR` type supplied to it at construction. The managed object of
236/// parameterized `TYPE` must have been created using memory provided by
237/// this allocator (or pool), which must remain valid throughout the
238/// lifetime of the proctor object.
239///
240/// See @ref bslma_rawdeleterproctor
241template <class TYPE, class ALLOCATOR>
243
244 // DATA
245 TYPE *d_object_p; // managed object
246 ALLOCATOR *d_allocator_p; // allocator or pool (held, not owned)
247
248 // NOT IMPLEMENTED
250 RawDeleterProctor& operator=(const RawDeleterProctor&);
251
252 public:
253 // CREATORS
254
255 /// Create a raw deleter proctor that conditionally manages the
256 /// specified `object` (if non-zero), and that uses the specified
257 /// `allocator` to delete the object managed by this proctor (if not
258 /// released -- see `release`) upon destruction. The behavior is
259 /// undefined unless `allocator` is non-zero and supplied the memory for
260 /// `object` (if non-zero). Note that `allocator` must remain valid
261 /// throughout the lifetime of this proctor.
262 RawDeleterProctor(TYPE *object, ALLOCATOR *allocator);
263
264 /// Destroy this raw deleter proctor, and delete the object it manages
265 /// (if any) by first invoking the destructor of the (managed) object,
266 /// and then invoking the `deallocate` method of the allocator (or pool)
267 /// that was supplied at the construction of this proctor. If no object
268 /// is currently being managed, this method has no effect.
270
271 // MANIPULATORS
272
273 /// Release from management the object currently managed by this
274 /// proctor. If no object is currently being managed, this method has
275 /// no effect.
276 void release();
277
278 /// Set the specified `object` as the object to be managed by this
279 /// proctor. The behavior is undefined unless `object` is non-zero and
280 /// was allocated from the allocator (or pool) supplied at construction.
281 /// Note that this method releases any previously-managed object from
282 /// management (without deleting it), and so may be invoked with or
283 /// without having called `release` when reusing this object.
284 void reset(TYPE *object);
285};
286
287// ============================================================================
288// INLINE DEFINITIONS
289// ============================================================================
290
291 // -----------------------
292 // class RawDeleterProctor
293 // -----------------------
294
295// CREATORS
296template <class TYPE, class ALLOCATOR>
297inline
299RawDeleterProctor(TYPE *object, ALLOCATOR *allocator)
300: d_object_p(object)
301, d_allocator_p(allocator)
302{
303 BSLS_ASSERT_SAFE(allocator);
304}
305
306template <class TYPE, class ALLOCATOR>
307inline
309{
310 BSLS_ASSERT_SAFE(d_allocator_p);
311
312 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(0 != d_object_p)) {
313 DeleterHelper::deleteObjectRaw(d_object_p, d_allocator_p);
314 }
315}
316
317// MANIPULATORS
318template <class TYPE, class ALLOCATOR>
319inline
321{
322 d_object_p = 0;
323}
324
325template <class TYPE, class ALLOCATOR>
326inline
328{
329 BSLS_ASSERT_SAFE(object);
330
331 d_object_p = object;
332}
333
334} // close package namespace
335
336
337#endif
338
339// ----------------------------------------------------------------------------
340// Copyright 2013 Bloomberg Finance L.P.
341//
342// Licensed under the Apache License, Version 2.0 (the "License");
343// you may not use this file except in compliance with the License.
344// You may obtain a copy of the License at
345//
346// http://www.apache.org/licenses/LICENSE-2.0
347//
348// Unless required by applicable law or agreed to in writing, software
349// distributed under the License is distributed on an "AS IS" BASIS,
350// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
351// See the License for the specific language governing permissions and
352// limitations under the License.
353// ----------------------------- END-OF-FILE ----------------------------------
354
355/** @} */
356/** @} */
357/** @} */
Definition bslma_rawdeleterproctor.h:242
void release()
Definition bslma_rawdeleterproctor.h:320
~RawDeleterProctor()
Definition bslma_rawdeleterproctor.h:308
void reset(TYPE *object)
Definition bslma_rawdeleterproctor.h:327
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1762
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(expr)
Definition bsls_performancehint.h:452
Definition balxml_encoderoptions.h:68
static void deleteObjectRaw(const TYPE *object, ALLOCATOR *allocator)
Definition bslma_deleterhelper.h:217