BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslma_destructorproctor.h
Go to the documentation of this file.
1/// @file bslma_destructorproctor.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslma_destructorproctor.h -*-C++-*-
8#ifndef INCLUDED_BSLMA_DESTRUCTORPROCTOR
9#define INCLUDED_BSLMA_DESTRUCTORPROCTOR
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslma_destructorproctor bslma_destructorproctor
15/// @brief Provide a proctor to conditionally manage an object.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslma
19/// @{
20/// @addtogroup bslma_destructorproctor
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslma_destructorproctor-purpose"> Purpose</a>
25/// * <a href="#bslma_destructorproctor-classes"> Classes </a>
26/// * <a href="#bslma_destructorproctor-description"> Description </a>
27/// * <a href="#bslma_destructorproctor-usage"> Usage </a>
28///
29/// # Purpose {#bslma_destructorproctor-purpose}
30/// Provide a proctor to conditionally manage an object.
31///
32/// # Classes {#bslma_destructorproctor-classes}
33///
34/// - bslma::DestructorProctor: proctor to conditionally manage an object
35///
36/// @see bslma_destructorguard, bslma_autodestructor
37///
38/// # Description {#bslma_destructorproctor-description}
39/// This component provides a proctor class template,
40/// `bslma::DestructorProctor`, to conditionally manage an (otherwise-unmanaged)
41/// object of parameterized `TYPE` supplied at construction. If not explicitly
42/// released, the managed object is destroyed automatically when the proctor
43/// object goes out of scope by calling the object's destructor. Note that
44/// after a proctor object releases its managed object, the same proctor can be
45/// reused to conditionally manage another object by invoking the `reset`
46/// method.
47///
48/// ## Usage {#bslma_destructorproctor-usage}
49///
50///
51/// The `bslma::DestructorProctor` is normally used to manage objects that are
52/// constructed sequentially in a block of memory provided. This is often the
53/// case when memory management and primitive helpers are implemented in
54/// different components. An example would be the construction of a pair object
55/// within another container with the help of a scalar primitive helper (see
56/// @ref bslma_constructionutil ). After the first object is constructed in the
57/// provided memory, it should be protected in case the constructor of the
58/// second object throws. The following example illustrates a typical use of
59/// the `bslma::DestructorProctor`.
60///
61/// First, suppose we have a pair class similar to `std::pair`:
62/// @code
63/// // MyPair.h
64/// // ...
65///
66/// /// This class provides a pair container to pair two different objects,
67/// /// one of parameterized `TYPE1`, and the other of parameterized
68/// /// `TYPE2`.
69/// template <class TYPE1, class TYPE2>
70/// class MyPair {
71///
72/// public:
73/// // PUBLIC TYPES
74/// typedef TYPE1 firstType;
75/// typedef TYPE2 secondType;
76///
77/// // PUBLIC DATA
78/// TYPE1 first; // first object
79/// TYPE2 second; // second object
80///
81/// // Declare trait `my_PairTrait`.
82/// // ...
83///
84/// public:
85/// // CREATORS
86/// // ...
87///
88/// /// Create a `MyPair` object that holds a copy of the specified
89/// /// `iFirst` and `iSecond`. Optionally specify `basicAllocator` to
90/// /// supply memory. If `basicAllocator` is zero, the global default
91/// /// allocator will be used to supply memory.
92/// MyPair(const TYPE1& iFirst,
93/// const TYPE2& iSecond,
94/// bslma::Allocator *basic_Allocator = 0)
95/// : first(iFirst)
96/// , second(iSecond)
97/// , d_allocator_p(bslma::Default::allocator(basic_Allocator))
98/// {
99/// }
100///
101/// // ...
102///
103/// };
104/// @endcode
105/// Note that parts of the implementation, including the `my_PairTrait`
106/// declaration, are elided. The `my_PairTrait` will be used by the primitive
107/// helper to customize implementations for objects that are pairs.
108///
109/// We now implement the primitive helper:
110/// @code
111/// // MyPrimitives.h
112/// // ...
113///
114/// /// This `struct` provides a namespace for primitive functions used to
115/// /// construct, destroy, insert, append and remove objects.
116/// struct MyPrimitives {
117///
118/// private:
119/// // PRIVATE TYPES
120/// enum { PAIR_TRAIT = 1, NIL_TRAIT = 0 };
121///
122/// public:
123/// // CLASS METHODS
124///
125/// /// Copy construct the specified `original` into the specified
126/// /// `address` using the specified `basicAllocator` (if the
127/// /// copy constructor of `TYPE` takes an allocator).
128/// template <class TYPE>
129/// static void copyConstruct(TYPE *address,
130/// const TYPE& original,
131/// bslma::Allocator *basicAllocator);
132///
133/// /// Copy construct the specified `original` into the specified
134/// /// `address` using the specified `basicAllocator` (if the
135/// /// copy constructor of `TYPE` takes an allocator). Note that
136/// /// the last parameter is used only for overload resolution.
137/// template <class TYPE>
138/// static void copyConstruct(TYPE *address,
139/// const TYPE& original,
140/// bslma::Allocator *basicAllocator,
141/// bsl::integral_constant<bool, PAIR_TRAIT> *);
142///
143/// /// Copy construct the specified `original` into the specified
144/// /// `address` using the specified `basicAllocator` (if the
145/// /// copy constructor of `TYPE` takes an allocator). Note that
146/// /// the last parameter is used only for overload resolution.
147/// template <class TYPE>
148/// static void copyConstruct(TYPE *address,
149/// const TYPE& original,
150/// bslma::Allocator *basicAllocator,
151/// bsl::integral_constant<bool, NIL_TRAIT> *);
152/// };
153///
154/// template <class TYPE>
155/// inline
156/// void MyPrimitives::copyConstruct(TYPE *address,
157/// const TYPE& original,
158/// bslma::Allocator *basicAllocator)
159/// {
160/// copyConstruct(address,
161/// original,
162/// basicAllocator,
163/// (typename my_HasPairTrait<TYPE>::type *)0);
164/// }
165/// @endcode
166/// The implementation of `copyConstruct` constructs the pair object in two
167/// steps because of the use of allocators. We cannot simply pass the allocator
168/// to the copy constructor of the pair object (since `std::pair` does not take
169/// an allocator). Therefore, we copy construct `first` and `second` directly
170/// in the pair object.
171/// @code
172/// template <class TYPE>
173/// inline
174/// void MyPrimitives::copyConstruct(TYPE *address,
175/// const TYPE& original,
176/// bslma::Allocator *basicAllocator,
177/// bsl::integral_constant<int, PAIR_TRAIT> *)
178/// {
179/// copyConstruct(&address->first, original.first, basicAllocator);
180///
181/// //**************************************************
182/// // Note the use of the destructor proctor (below). *
183/// //**************************************************
184///
185/// bslma::DestructorProctor<typename TYPE::firstType> proctor(
186/// &address->first);
187///
188/// copyConstruct(&address->second, original.second, basicAllocator);
189///
190/// //********************************************************
191/// // Note that the destructor proctor is released (below). *
192/// //********************************************************
193///
194/// proctor.release();
195/// }
196///
197/// template <class TYPE>
198/// inline
199/// void MyPrimitives::copyConstruct(TYPE *address,
200/// const TYPE& original,
201/// bslma::Allocator *basicAllocator,
202/// bsl::integral_constant<int, NIL_TRAIT> *)
203/// {
204/// new(address)TYPE(original, basicAllocator);
205/// }
206/// @endcode
207/// Note that the implementation of `my_HasPairTrait` is not shown. It is used
208/// to detect whether `TYPE` has `my_PairTrait` or not (see @ref bslalg_typetraits ,
209/// @ref bslalg_typetraitpair ).
210///
211/// In the above implementation, if the copy construction of the second object
212/// in the pair throws, all memory (and any other resources) acquired as a
213/// result of copying the (not-yet-managed) object would be leaked. Using the
214/// `bslma::DestructorProctor` prevents the leaks by invoking the destructor of
215/// the proctored object automatically should the proctor go out of scope before
216/// the `release` method of the proctor is called (such as when the function
217/// exits prematurely due to an exception).
218///
219/// Note that the `copyConstruct` method assumes the copy constructor of
220/// `TYPE::firstType` and `TYPE::secondType` takes an allocator as a second
221/// argument. In production code, a constructor proxy that checks the traits of
222/// `TYPE::firstType` and `TYPE::secondType` (to determine whether they uses
223/// `bslma::Allocator`) should be used (see @ref bslalg_constructorproxy ).
224/// @}
225/** @} */
226/** @} */
227
228/** @addtogroup bsl
229 * @{
230 */
231/** @addtogroup bslma
232 * @{
233 */
234/** @addtogroup bslma_destructorproctor
235 * @{
236 */
237
238#include <bslscm_version.h>
239
241
242#include <bsls_assert.h>
243#include <bsls_performancehint.h>
244
245
246
247namespace bslma {
248
249 // =======================
250 // class DestructorProctor
251 // =======================
252
253/// This class implements a proctor that, unless its `release` method has
254/// previously been invoked, automatically destroys a managed object upon
255/// destruction by invoking the (managed) object's destructor.
256///
257/// See @ref bslma_destructorproctor
258template <class TYPE>
260
261 // DATA
262 TYPE *d_object_p; // managed object
263
264 private:
265 // NOT IMPLEMENTED
267 DestructorProctor& operator=(const DestructorProctor&);
268
269 public:
270 // CREATORS
271
272 /// Create a destructor proctor that conditionally manages the specified
273 /// `object` (if non-zero) by invoking the destructor of the object
274 /// managed by this proctor (if not released -- see `release`) upon
275 /// destruction.
276 explicit DestructorProctor(TYPE *object);
277
278 /// Destroy this destructor proctor, and destroy the object it manages
279 /// (if any) by invoking the destructor of the (managed) object. If no
280 /// object is currently being managed, this method has no effect.
282
283 // MANIPULATORS
284
285 /// Release from management the object currently managed by this
286 /// proctor. If no object is currently being managed, this method has
287 /// no effect.
288 void release();
289
290 /// Set the specified `object` as the object to be managed by this proctor.
291 ///
292 /// \pre The behavior is undefined unless `object` is non-zero.
293 ///
294 /// \note Note that this method releases any previously-managed object from
295 /// management (without destroying it), and so may be invoked with or
296 /// without having called `release` when reusing this object.
297 void reset(TYPE *object);
298};
299
300// ============================================================================
301// INLINE DEFINITIONS
302// ============================================================================
303
304 // -----------------------
305 // class DestructorProctor
306 // -----------------------
307
308// CREATORS
309template <class TYPE>
310inline
312: d_object_p(object)
313{
314}
315
316template <class TYPE>
317inline
319{
320 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(0 != d_object_p)) {
321 DestructionUtil::destroy(d_object_p);
322 }
323}
324
325// MANIPULATORS
326template <class TYPE>
327inline
329{
330 d_object_p = 0;
331}
332
333template <class TYPE>
334inline
336{
337 BSLS_ASSERT_SAFE(object);
338
339 d_object_p = object;
340}
341
342} // close package namespace
343
344#ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY
345// ============================================================================
346// BACKWARD COMPATIBILITY
347// ============================================================================
348
349#ifdef bslma_DestructorProctor
350#undef bslma_DestructorProctor
351#endif
352/// This alias is defined for backward compatibility.
353#define bslma_DestructorProctor bslma::DestructorProctor
354#endif // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY
355
356
357
358#endif
359
360// ----------------------------------------------------------------------------
361// Copyright 2013 Bloomberg Finance L.P.
362//
363// Licensed under the Apache License, Version 2.0 (the "License");
364// you may not use this file except in compliance with the License.
365// You may obtain a copy of the License at
366//
367// http://www.apache.org/licenses/LICENSE-2.0
368//
369// Unless required by applicable law or agreed to in writing, software
370// distributed under the License is distributed on an "AS IS" BASIS,
371// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
372// See the License for the specific language governing permissions and
373// limitations under the License.
374// ----------------------------- END-OF-FILE ----------------------------------
375
376/** @} */
377/** @} */
378/** @} */
Definition bslma_destructorproctor.h:259
~DestructorProctor()
Definition bslma_destructorproctor.h:318
void release()
Definition bslma_destructorproctor.h:328
void reset(TYPE *object)
Definition bslma_destructorproctor.h:335
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1917
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(expr)
Definition bsls_performancehint.h:452
Definition baljsn_encoder_testtypes.h:76