BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslalg_autoarraydestructor.h
Go to the documentation of this file.
1/// @file bslalg_autoarraydestructor.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslalg_autoarraydestructor.h -*-C++-*-
8#ifndef INCLUDED_BSLALG_AUTOARRAYDESTRUCTOR
9#define INCLUDED_BSLALG_AUTOARRAYDESTRUCTOR
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslalg_autoarraydestructor bslalg_autoarraydestructor
15/// @brief Provide a proctor for destroying arrays.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslalg
19/// @{
20/// @addtogroup bslalg_autoarraydestructor
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslalg_autoarraydestructor-purpose"> Purpose</a>
25/// * <a href="#bslalg_autoarraydestructor-classes"> Classes </a>
26/// * <a href="#bslalg_autoarraydestructor-description"> Description </a>
27/// * <a href="#bslalg_autoarraydestructor-usage"> Usage </a>
28/// * <a href="#bslalg_autoarraydestructor-example-1-managing-an-array-under-construction"> Example 1: Managing an Array Under Construction </a>
29///
30/// # Purpose {#bslalg_autoarraydestructor-purpose}
31/// Provide a proctor for destroying arrays.
32///
33/// # Classes {#bslalg_autoarraydestructor-classes}
34///
35/// - bslalg::AutoArrayDestructor: exception-neutrality proctor for arrays
36///
37/// @see bslma_autodestructor
38///
39/// # Description {#bslalg_autoarraydestructor-description}
40/// This component provides a proctor object to manage a contiguous
41/// (in-place) sequence of otherwise-unmanaged instances of a user-defined type.
42/// If not explicitly released, all objects managed by the proctor object are
43/// automatically destroyed by the proctor's destructor, using the
44/// @ref bslalg_arraydestructionprimitives .
45///
46/// In most instances, `bslma::AutoDestructor` can also be used, but this
47/// component is more useful in cases where it is simpler to think in terms of
48/// two pointers at the ends of the array being managed, rather than an origin
49/// and offset.
50///
51/// ## Usage {#bslalg_autoarraydestructor-usage}
52///
53///
54/// In this section we show intended use of this component.
55///
56/// ### Example 1: Managing an Array Under Construction {#bslalg_autoarraydestructor-example-1-managing-an-array-under-construction}
57///
58///
59/// In most instances, the use of a `bslalg::AutoArrayDestructor` could be
60/// handled by a `bslma::AutoDeallocator`, but sometimes it is conceptually
61/// clearer to frame the problem in terms of a pair of pointers rather than a
62/// pointer and an offset.
63///
64/// Suppose we have a class, `UsageType` that allocates a block of memory upon
65/// construction, and whose constructor takes a `char`. Suppose we want to
66/// create an array of elements of such objects in an exception-safe manner.
67///
68/// First, we create the type `UsageType`:
69/// @code
70/// // ===============
71/// // class UsageType
72/// // ===============
73///
74/// /// This test type contains a 'char' in some allocated storage. It has
75/// /// no traits other than using a 'bslma' allocator.
76/// class UsageType {
77///
78/// char *d_data_p; // managed single char
79/// bslma::Allocator *d_allocator_p; // allocator (held, not owned)
80///
81/// public:
82/// // CREATORS
83/// explicit UsageType(char c, bslma::Allocator *basicAllocator = 0)
84/// : d_data_p(0)
85/// , d_allocator_p(bslma::Default::allocator(basicAllocator))
86/// {
87/// d_data_p = (char *)d_allocator_p->allocate(sizeof(char));
88/// *d_data_p = c;
89/// }
90///
91/// ~UsageType()
92/// {
93/// *d_data_p = '_';
94/// d_allocator_p->deallocate(d_data_p);
95/// d_data_p = 0;
96/// }
97///
98/// // ACCESSORS
99/// char datum() const
100/// {
101/// return *d_data_p;
102/// }
103/// };
104///
105/// namespace BloombergLP {
106/// namespace bslma {
107///
108/// template <>
109/// struct UsesBslmaAllocator<UsageType> : bsl::true_type {};
110///
111/// } // close package namespace
112/// } // close enterprise namespace
113/// @endcode
114/// Then, in `main`, we create a `TestAllocator` to supply memory (and to verify
115/// that no memory is leaked):
116/// @code
117/// bslma::TestAllocator ta;
118/// @endcode
119/// Next, we create the pointer for our array:
120/// @code
121/// UsageType *array;
122/// @endcode
123/// Then, we declare a string of characters we will use to initialize the
124/// `UsageType` objects in our array.
125/// @code
126/// const char *DATA = "Hello";
127/// const size_t DATA_LEN = std::strlen(DATA);
128/// @endcode
129/// Next, we verify that even right after exceptions have been thrown and
130/// caught, no memory is outstanding:
131/// @code
132/// assert(0 == ta.numBlocksInUse());
133/// @endcode
134/// Then, we allocate our array and create a guard to free it if a subsequent
135/// allocation throws an exception:
136/// @code
137/// array = (UsageType *) ta.allocate(DATA_LEN * sizeof(UsageType));
138/// bslma::DeallocatorProctor<bslma::Allocator> arrayProctor(array, &ta);
139/// @endcode
140/// Next, we establish an `AutoArrayDestructor` on `array` to destroy any valid
141/// elements in `array` if an exception is thrown:
142/// @code
143/// bslalg::AutoArrayDestructor<UsageType,> arrayElementProctor(array, array);
144/// @endcode
145/// Notice that we pass `arrayElementProctor` pointers to the beginning and end
146/// of the range to be guarded (we start with an empty range since no elements
147/// have been constructed yet).
148///
149/// Then, we iterate through the valid chars in `DATA` and use them to construct
150/// the elements of the array:
151/// @code
152/// UsageType *resultElement = array;
153/// for (const char *nextChar = DATA; *nextChar; ++nextChar) {
154/// @endcode
155/// Next, construct the next element of `array`:
156/// @code
157/// new (resultElement++) UsageType(*nextChar, &ta);
158/// @endcode
159/// Now, move the end of `arrayElementProctor` to cover the most recently
160/// constructed element:
161/// @code
162/// arrayElementProctor.moveEnd(1);
163/// }
164/// @endcode
165/// At this point, we have successfully created our array.
166///
167/// Then, release the guards so they won't destroy our work when they go out of
168/// scope:
169/// @code
170/// arrayProctor.release();
171/// arrayElementProctor.release();
172/// @endcode
173/// Next, exit the exception testing block:
174///
175/// Then, verify that the array we have created is as expected:
176/// @code
177/// assert('H' == array[0].datum());
178/// assert('e' == array[1].datum());
179/// assert('l' == array[2].datum());
180/// assert('l' == array[3].datum());
181/// assert('o' == array[4].datum());
182/// @endcode
183/// Finally, destroy & free our work and verify that no memory is leaked:
184/// @code
185/// for (size_t i = 0; i < DATA_LEN; ++i) {
186/// array[i].~UsageType();
187/// }
188/// ta.deallocate(array);
189///
190/// assert(0 == ta.numBlocksInUse());
191/// @endcode
192/// @}
193/** @} */
194/** @} */
195
196/** @addtogroup bsl
197 * @{
198 */
199/** @addtogroup bslalg
200 * @{
201 */
202/** @addtogroup bslalg_autoarraydestructor
203 * @{
204 */
205
206#include <bslscm_version.h>
207
209
210#include <bslma_bslallocator.h>
211
212#include <bsls_assert.h>
213
214#include <cstddef> // size_t
215
216
217
218namespace bslalg {
219
220 // =========================
221 // class AutoArrayDestructor
222 // =========================
223
224/// This `class` provides a specialized proctor object that, upon
225/// destruction and unless the `release` method has been called, destroys
226/// the elements in a segment of an array of parameterized type
227/// `OBJECT_TYPE`. The elements destroyed are delimited by the "guarded"
228/// range `[ begin(), end() )`.
229///
230/// See @ref bslalg_autoarraydestructor
231template <class OBJECT_TYPE, class ALLOCATOR = bsl::allocator<OBJECT_TYPE> >
233
234 // DATA
235 OBJECT_TYPE *d_begin_p; // address of first element in guarded range
236 OBJECT_TYPE *d_end_p; // first address beyond last element in guarded
237 // range
238 ALLOCATOR d_allocator; // allocator
239
240 private:
241 // NOT IMPLEMENTED
243 AutoArrayDestructor& operator=(const AutoArrayDestructor&);
244
245 public:
246 // TYPES
247 typedef std::ptrdiff_t difference_type;
248
249 // CREATORS
250
251 /// Create an array exception guard object for the sequence of elements
252 /// of the parameterized `OBJECT_TYPE` delimited by the range specified
253 /// by `[ begin, end )`. The behavior is undefined unless
254 /// `begin <= end` and each element in the range `[ begin, end )` has
255 /// been initialized.
256 AutoArrayDestructor(OBJECT_TYPE *begin, OBJECT_TYPE *end,
257 ALLOCATOR allocator = ALLOCATOR());
258
259 /// Call the destructor on each of the elements of the parameterized
260 /// `OBJECT_TYPE` delimited by the range `[ begin(), end() )` and
261 /// destroy this array exception guard.
263
264 // MANIPULATORS
265
266 /// Move the begin pointer by the specified `offset`, and return the new
267 /// begin pointer.
268 OBJECT_TYPE *moveBegin(difference_type offset = -1);
269
270 /// Move the end pointer by the specified `offset`, and return the new
271 /// end pointer.
272 OBJECT_TYPE *moveEnd(difference_type offset = 1);
273
274 /// Set the range of elements guarded by this object to be empty. Note
275 /// that `begin() == end()` following this operation, but the specific
276 /// value is unspecified.
277 void release();
278};
279
280// ============================================================================
281// INLINE FUNCTION DEFINITIONS
282// ============================================================================
283
284 // -------------------------
285 // class AutoArrayDestructor
286 // -------------------------
287
288// CREATORS
289template <class OBJECT_TYPE, class ALLOCATOR>
290inline
292 OBJECT_TYPE *begin,
293 OBJECT_TYPE *end,
294 ALLOCATOR allocator)
295: d_begin_p(begin)
296, d_end_p(end)
297, d_allocator(allocator)
298{
299 BSLS_ASSERT_SAFE(!begin == !end);
300 BSLS_ASSERT_SAFE(begin <= end);
301}
302
303template <class OBJECT_TYPE, class ALLOCATOR>
304inline
306{
307 BSLS_ASSERT_SAFE(!d_begin_p == !d_end_p);
308 BSLS_ASSERT_SAFE(d_begin_p <= d_end_p);
309
310 ArrayDestructionPrimitives::destroy(d_begin_p, d_end_p, d_allocator);
311}
312
313// MANIPULATORS
314template <class OBJECT_TYPE, class ALLOCATOR>
315inline
317 difference_type offset)
318{
319 BSLS_ASSERT_SAFE(d_begin_p || 0 == offset);
320 BSLS_ASSERT_SAFE(d_end_p - d_begin_p >= offset);
321
322 d_begin_p += offset;
323 return d_begin_p;
324}
325
326template <class OBJECT_TYPE, class ALLOCATOR>
327inline
328OBJECT_TYPE *
330{
331 BSLS_ASSERT_SAFE(d_end_p || 0 == offset);
332 BSLS_ASSERT_SAFE(d_end_p - d_begin_p >= -offset);
333
334 d_end_p += offset;
335 return d_end_p;
336}
337
338template <class OBJECT_TYPE, class ALLOCATOR>
339inline
341{
342 d_begin_p = d_end_p;
343}
344
345} // close package namespace
346
347#ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY
348// ============================================================================
349// BACKWARD COMPATIBILITY
350// ============================================================================
351
352#ifdef bslalg_AutoArrayDestructor
353#undef bslalg_AutoArrayDestructor
354#endif
355/// This alias is defined for backward compatibility.
356#define bslalg_AutoArrayDestructor bslalg::AutoArrayDestructor
357#endif // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY
358
359
360
361#endif
362
363// ----------------------------------------------------------------------------
364// Copyright 2013 Bloomberg Finance L.P.
365//
366// Licensed under the Apache License, Version 2.0 (the "License");
367// you may not use this file except in compliance with the License.
368// You may obtain a copy of the License at
369//
370// http://www.apache.org/licenses/LICENSE-2.0
371//
372// Unless required by applicable law or agreed to in writing, software
373// distributed under the License is distributed on an "AS IS" BASIS,
374// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
375// See the License for the specific language governing permissions and
376// limitations under the License.
377// ----------------------------- END-OF-FILE ----------------------------------
378
379/** @} */
380/** @} */
381/** @} */
Definition bslalg_autoarraydestructor.h:232
OBJECT_TYPE * moveEnd(difference_type offset=1)
Definition bslalg_autoarraydestructor.h:329
OBJECT_TYPE * moveBegin(difference_type offset=-1)
Definition bslalg_autoarraydestructor.h:316
void release()
Definition bslalg_autoarraydestructor.h:340
std::ptrdiff_t difference_type
Definition bslalg_autoarraydestructor.h:247
~AutoArrayDestructor()
Definition bslalg_autoarraydestructor.h:305
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1762
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdlc_flathashmap.h:1805
static void destroy(TARGET_TYPE *begin, TARGET_TYPE *end, ALLOCATOR allocator, bsl::true_type)
Definition bslalg_arraydestructionprimitives.h:232