BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslstl_sharedptrallocateinplacerep.h
Go to the documentation of this file.
1/// @file bslstl_sharedptrallocateinplacerep.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslstl_sharedptrallocateinplacerep.h -*-C++-*-
8#ifndef INCLUDED_BSLSTL_SHAREDPTRALLOCATEINPLACEREP
9#define INCLUDED_BSLSTL_SHAREDPTRALLOCATEINPLACEREP
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id$ $CSID$")
13
14/// @defgroup bslstl_sharedptrallocateinplacerep bslstl_sharedptrallocateinplacerep
15/// @brief Provide an in-place implementation of `bslma::SharedPtrRep`.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslstl
19/// @{
20/// @addtogroup bslstl_sharedptrallocateinplacerep
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslstl_sharedptrallocateinplacerep-purpose"> Purpose</a>
25/// * <a href="#bslstl_sharedptrallocateinplacerep-classes"> Classes </a>
26/// * <a href="#bslstl_sharedptrallocateinplacerep-description"> Description </a>
27/// * <a href="#bslstl_sharedptrallocateinplacerep-thread-safety"> Thread Safety </a>
28///
29/// # Purpose {#bslstl_sharedptrallocateinplacerep-purpose}
30/// Provide an in-place implementation of `bslma::SharedPtrRep`.
31///
32/// # Classes {#bslstl_sharedptrallocateinplacerep-classes}
33///
34/// - bslstl::SharedPtrAllocateInplaceRep: in-place `shared_ptr` implementation
35///
36/// **Canonical header:** bsl_memory.h
37///
38/// @see bslma_sharedptrrep, bslma_sharedptrinplacerep, bslstl_sharedptr
39///
40/// # Description {#bslstl_sharedptrallocateinplacerep-description}
41/// This component provides a class template,
42/// `bslstl::SharedPtrAllocateInplaceRep`, proving a concrete implementation of
43/// `bslma::SharedPtrRep` for managing objects of the parameterized `TYPE` that
44/// are stored in-place in the representation, and are allocated by an allocator
45/// that satisfies the requirements of an Allocator type in the C++11 standard.
46/// Thus, only one memory allocation is required to create both the
47/// representation and the managed object. When all references to the in-place
48/// object are released (using `releaseRef`), the destructor of `TYPE` is
49/// invoked.
50///
51/// ## Thread Safety {#bslstl_sharedptrallocateinplacerep-thread-safety}
52///
53///
54/// `bslstl::SharedPtrAllocateInplaceRep` is thread-safe provided that
55/// `disposeObject` and `disposeRep` are not called explicitly, meaning that all
56/// non-creator operations other than `disposeObject` and `disposeRep` on a
57/// given instance can be safely invoked simultaneously from multiple threads
58/// (`disposeObject` and `disposeRep` are meant to be invoked only by
59/// `releaseRef` and `releaseWeakRef`). Note that there is no thread safety
60/// guarantees for operations on the managed object contained in
61/// `bslstl::SharedPtrAllocateInplaceRep`.
62/// @}
63/** @} */
64/** @} */
65
66/** @addtogroup bsl
67 * @{
68 */
69/** @addtogroup bslstl
70 * @{
71 */
72/** @addtogroup bslstl_sharedptrallocateinplacerep
73 * @{
74 */
75
76#include <bslscm_version.h>
77
79#include <bslma_sharedptrrep.h>
81
82#include <bslmf_isarray.h>
83#include <bslmf_assert.h>
84
86#include <bsls_alignmentutil.h>
87#include <bsls_assert.h>
88#include <bsls_keyword.h>
89#include <bsls_objectbuffer.h>
90#include <bsls_types.h>
91
92#include <new>
93#include <stddef.h> // 'size_t'
94#include <stdint.h> // 'uintptr_t'
95#include <typeinfo>
96
97
98namespace bslstl {
99
100 // =================================
101 // class SharedPtrAllocateInplaceRep
102 // =================================
103
104/// This class provides a concrete implementation of the `SharedPtrRep`
105/// protocol for in-place instances of the (template parameter) `TYPE`.
106/// Upon destruction of this object, the destructor of `TYPE` is invoked on
107/// the shared object.
108///
109/// See @ref bslstl_sharedptrallocateinplacerep
110template <class TYPE, class ALLOCATOR>
111class SharedPtrAllocateInplaceRep : public BloombergLP::bslma::SharedPtrRep {
112
113 // PRIVATE TYPES
114 typedef typename bsl::allocator_traits<ALLOCATOR>::
115 template rebind_traits<SharedPtrAllocateInplaceRep>
116 ReboundTraits;
117
118 public:
119 // PUBLIC TYPES
120 typedef typename ReboundTraits::allocator_type ReboundAllocator;
121
122 private:
123 // DATA
124 ReboundAllocator d_allocator; // copy of this object's allocator
125 bsls::ObjectBuffer<TYPE> d_instance; // beginning of the in-place buffer
126
127 // Note that `d_instance` must be last in this layout to allow for the
128 // possibility of creating an in-place uninitialized buffer, where it is
129 // possible to access memory beyond the `d_instance` footprint (refer to
130 // `bsl::shared_ptr::createInplaceUninitializedBuffer` for sample usage).
131
132 private:
133 // NOT IMPLEMENTED
136
137 // PRIVATE CREATORS
138
139 /// Create a `SharedPtrAllocateInplaceRep` object having uninitialized
140 /// storage for an in-place instance of the parameterized `TYPE`. Use
141 /// the specified `basicAllocator` to supply memory and, upon a call to
142 /// `disposeObject`, to destroy the inplace object, and upon a call to
143 /// `disposeRep` to destroy the copy the allocator and reclaim storage
144 /// for this object.
146 const ReboundAllocator& basicAllocator);
147
148 /// The destructor for this object should never be called. The in-place
149 /// `TYPE` object will be destroyed by a call to `disposeObject` and the
150 /// stored allocator for this object will be destroyed by a call to
151 /// `disposeRep`, which will then reclaim the storage occupied by this
152 /// object.
154
155 public:
156 // CLASS METHODS
157
158 /// Create a `SharedPtrAllocateInplaceRep` object having storage for an
159 /// in-place uninitialized object of (template parameter) `TYPE`, and
160 /// return its address. Use the specified `basicAllocator` to supply
161 /// memory and, upon a call to `disposeRep`, to destroy this
162 /// representation (and the in-place shared object). Note that the
163 /// function members `ptr` and `originalPtr` will return the address of
164 /// an uninitialized object. This object should be explicitly
165 /// initialized by the caller, and it is undefined behavior to call
166 /// `disposeRep` until this object has been successfully constructed.
168 ReboundAllocator basicAllocator);
169
170 // MANIPULATORS
171
172 /// Destroy the object being referred to by this representation. This
173 /// method is automatically invoked by `releaseRef` when the number of
174 /// shared references reaches zero and should not be explicitly invoked
175 /// otherwise.
177
178 /// Destroy this representation object and deallocate the associated
179 /// memory. This method is automatically invoked by `releaseRef` and
180 /// `releaseWeakRef` when the number of weak references and the number
181 /// of shared references both reach zero and should not be explicitly
182 /// invoked otherwise. The behavior is undefined unless `disposeObject`
183 /// has already been called for this representation. Note that this
184 /// method effectively serves as the representation object's destructor.
186
187 /// Ignore the specified `type` and return a null pointer. Note that
188 /// there is no facility for the user to supply a deleter for an
189 /// in-place representation for a shared pointer.
190 void *getDeleter(const std::type_info& type) BSLS_KEYWORD_OVERRIDE;
191
192 /// Return the address of the modifiable shared object to which this
193 /// object refers. Note that in order to return a pointer to a
194 /// modifiable object, this function cannot be `const` qualified as the
195 /// referenced object is stored internally as a data member.
196 TYPE *ptr();
197
198 // ACCESSORS
199
200 /// Return the (untyped) address of the modifiable shared object to
201 /// which this object refers.
203};
204
205
206 // ======================================
207 // class SharedPtrArrayAllocateInplaceRep
208 // ======================================
209
210/// This class provides a concrete implementation of the `SharedPtrRep`
211/// protocol for in-place instances of the (template parameter) `TYPE`,
212/// which must be an array. Upon destruction of this object, each element
213/// of the array is destructed.
214template <class TYPE, class ALLOCATOR>
216 : public BloombergLP::bslma::SharedPtrRep {
217
218 private:
219 // PRIVATE TYPES
220 typedef typename bsl::allocator_traits<ALLOCATOR>::
221 template rebind_traits<SharedPtrArrayAllocateInplaceRep>
222 ReboundTraits;
223
224 public:
225 // PUBLIC TYPES
227 typedef typename ReboundTraits::allocator_type ReboundAllocator;
228
229 private:
230 // DATA
231 ReboundAllocator d_allocator; // copy of the allocator
232 size_t d_size; // the number of elements
233 char *d_allocated_ptr_p; // the actual memory allocated
234 // The elements of the array stored in this Rep are created after the
235 // instance variables.
236
237 // NOT IMPLEMENTED
241
242 // PRIVATE CLASS METHODS
243
244 /// Return the offset (in bytes) from the start of the object to the
245 /// first element of the array stored at the end of the object.
246 static size_t offset_of_first_element();
247
248 // PRIVATE CREATORS
249
250 /// Create a `SharedPtrArrayAllocateInplaceRep` object having
251 /// uninitialized storage for an in-place instance of the parameterized
252 /// `TYPE` containing the specified `numElements` number of elements.
253 /// Use the specified `basicAllocator` to supply memory and, upon a call
254 /// to `disposeObject`, to destroy the inplace object , and upon a call
255 /// to `disposeRep` to destroy the copy the allocator and reclaim
256 /// storage for this object, pointed to by the specified `allocatedPtr`.
257 explicit SharedPtrArrayAllocateInplaceRep(size_t numElements,
258 const ReboundAllocator& basicAllocator,
259 char *allocatedPtr);
260
261 /// The destructor for this object should never be called. The in-place
262 /// `TYPE` object will be destroyed by a call to `disposeObject` and the
263 /// stored allocator for this object will be destroyed by a call to
264 /// `disposeRep`, which will then reclaim the storage occupied by this
265 /// object.
267
268 // PRIVATE ACCESSORS
269
270 /// Return a const pointer to the first element of the array stored at
271 /// the end of the object.
272 const element_type *get_pointer_to_first_element() const;
273
274 // PRIVATE MANIPULATORS
275
276 /// Return a pointer to the first element of the array stored at the end
277 /// of the object.
278 element_type *get_pointer_to_first_element();
279
280 public:
281 // CLASS METHODS
282
283 /// Return the size (in bytes) for an allocation to hold an object of
284 /// type `SharedPtrArrayAllocateInplaceRep<T[]>` containing the
285 /// specified `numElements` number of elements.
286 static size_t alloc_size(size_t numElements);
287
288 /// Create a `SharedPtrArrayAllocateInplaceRep` object having storage
289 /// for an in-place uninitialized sized array of (template parameter)
290 /// `TYPE` containing space for the specified `numElements` number of
291 /// elements, and return its address. Use the specified
292 /// `basicAllocator` to supply memory and, upon a call to `disposeRep`,
293 /// to destroy this representation (and the in-place shared object).
294 /// Note that the function members `ptr` and `originalPtr` will return
295 /// the address of an uninitialized array. This object should be
296 /// explicitly initialized by the caller, and it is undefined behavior
297 /// to call `disposeRep` until this object has been successfully
298 /// constructed.
300 ReboundAllocator basicAllocator,
301 size_t numElements);
302
303 // MANIPULATORS
304
305 /// Destroy the object being referred to by this representation. This
306 /// method is automatically invoked by `releaseRef` when the number of
307 /// shared references reaches zero and should not be explicitly invoked
308 /// otherwise.
310
311 /// Destroy this representation object and deallocate the associated
312 /// memory. This method is automatically invoked by `releaseRef` and
313 /// `releaseWeakRef` when the number of weak references and the number
314 /// of shared references both reach zero and should not be explicitly
315 /// invoked otherwise. The behavior is undefined unless `disposeObject`
316 /// has already been called for this representation. Note that this
317 /// method effectively serves as the representation object's destructor.
319
320 /// Ignore the specified `type` and return a null pointer. Note that
321 /// there is no facility for the user to supply a deleter for an
322 /// in-place representation for a shared pointer.
323 void *getDeleter(const std::type_info& type) BSLS_KEYWORD_OVERRIDE;
324
325 /// Return the address of the modifiable shared object to which this
326 /// object refers. Note that in order to return a pointer to a
327 /// modifiable object, this function cannot be `const` qualified as the
328 /// referenced object is stored internally.
329 element_type *ptr();
330
331 // ACCESSORS
332
333 /// Return the (untyped) address of the modifiable shared object to
334 /// which this object refers.
336};
337
338// ============================================================================
339// INLINE DEFINITIONS
340// ============================================================================
341
342 // ---------------------------------
343 // class SharedPtrAllocateInplaceRep
344 // ---------------------------------
345
346// PRIVATE CREATORS
347template <class TYPE, class ALLOCATOR>
348inline
350 const ReboundAllocator& basicAllocator)
351: d_allocator(basicAllocator)
352// 'd_instance' is intentionally left uninitialized.
353{
355}
356
357template <class TYPE, class ALLOCATOR>
360{
362}
363
364// CLASS METHODS
365template <class TYPE, class ALLOCATOR>
366inline
367SharedPtrAllocateInplaceRep<TYPE, ALLOCATOR> *
369 ReboundAllocator basicAllocator)
370{
372 ReboundTraits::allocate(basicAllocator, 1);
373 new(rep_p) SharedPtrAllocateInplaceRep(basicAllocator);
374 return rep_p;
375}
376
377// MANIPULATORS
378template <class TYPE, class ALLOCATOR>
379inline
381{
382 ReboundTraits::destroy(d_allocator, ptr());
383}
384
385template <class TYPE, class ALLOCATOR>
386inline
388{
389 ReboundAllocator alloc(d_allocator);
390 this->d_allocator.~ReboundAllocator();
391 ReboundTraits::deallocate(alloc, this, 1);
392}
393
394template <class TYPE, class ALLOCATOR>
395inline
396void *
398{
399 return 0;
400}
401
402template <class TYPE, class ALLOCATOR>
403inline
405{
406 return d_instance.address();
407}
408
409// ACCESSORS
410template <class TYPE, class ALLOCATOR>
411inline
412void *
414{
415 return const_cast<void *>(static_cast<const void *>(
416 const_cast<const TYPE *>(d_instance.address())));
417}
418
419
420 // --------------------------------------
421 // class SharedPtrArrayAllocateInplaceRep
422 // --------------------------------------
423
424// PRIVATE CREATORS
425template <class TYPE, class ALLOCATOR>
426inline
428SharedPtrArrayAllocateInplaceRep(size_t numElements,
429 const ReboundAllocator& basicAllocator,
430 char *allocatedPtr)
431: d_allocator(basicAllocator)
432, d_size(numElements)
433, d_allocated_ptr_p(allocatedPtr)
434{
436 BSLS_ASSERT_OPT(numElements > 0);
437}
438
439template <class TYPE, class ALLOCATOR>
440SharedPtrArrayAllocateInplaceRep<TYPE, ALLOCATOR>::
441~SharedPtrArrayAllocateInplaceRep()
442{
444}
445
446// PRIVATE CLASS METHODS
447template <class TYPE, class ALLOCATOR>
448inline
449size_t
450SharedPtrArrayAllocateInplaceRep<TYPE, ALLOCATOR>::offset_of_first_element()
451{
452 typedef SharedPtrArrayAllocateInplaceRep<TYPE, ALLOCATOR> ThisType;
453
454 enum {
456 k_ALIGNMENT_MASK = ~(k_ALIGNMENT - 1)
457 };
458
459 // We want the first multiple of 'k_ALIGNMENT' that is >= sizeof(*this). We
460 // assume that 'k_ALIGNMENT' is a power of two.
461 BSLMF_ASSERT((k_ALIGNMENT & (k_ALIGNMENT - 1)) == 0);
462 return (sizeof(ThisType) + k_ALIGNMENT - 1) & k_ALIGNMENT_MASK;
463}
464
465// CLASS METHODS
466template <class TYPE, class ALLOCATOR>
467inline
468size_t
470 size_t numElements)
471{
472 BSLS_ASSERT_OPT(numElements > 0);
473
475 return ThisType::offset_of_first_element() +
477 (sizeof(ThisType::element_type) * numElements);
478}
479
480template <class TYPE, class ALLOCATOR>
481inline
484 ReboundAllocator basicAllocator,
485 size_t numElements)
486{
487 BSLS_ASSERT_OPT(numElements > 0);
488
490 template rebind_traits<char> CharATraits;
491
492 enum {
494 k_ALIGNMENT_MASK = ~(k_ALIGNMENT - 1)
495 };
496
497 // Rebind the allocator because we need to allocate in units of bytes.
498 typename CharATraits::allocator_type charAlloc(basicAllocator);
499 char *char_p =
500 CharATraits::allocate(charAlloc, alloc_size(numElements));
501
502 // Align the pointer; convert it to an integer, add BSLS_MAX_ALIGNMENT -1,
503 // then mask off the low bits. We assume that 'BSLS_MAX_ALIGNMENT' is a
504 // power of two.
505 BSLMF_ASSERT((k_ALIGNMENT & (k_ALIGNMENT - 1)) == 0);
506 bsls::Types::UintPtr aligned =
507 (reinterpret_cast<bsls::Types::UintPtr>(char_p) + k_ALIGNMENT - 1) &
508 k_ALIGNMENT_MASK;
510 reinterpret_cast<SharedPtrArrayAllocateInplaceRep *>(aligned);
511
512 new (rep_p)
513 SharedPtrArrayAllocateInplaceRep(numElements, basicAllocator, char_p);
514 return rep_p;
515}
516
517// ACCESSORS
518template <class TYPE, class ALLOCATOR>
519inline
520typename
524{
525 return reinterpret_cast<element_type *>(
526 reinterpret_cast<char *>(this) + offset_of_first_element());
527}
528
529// MANIPULATORS
530template <class TYPE, class ALLOCATOR>
531inline
533{
534 typedef typename bsl::allocator_traits<ALLOCATOR>::
535 template rebind_traits<element_type> ElementTraits;
536
537 typename ElementTraits::allocator_type elementAlloc(d_allocator);
538
539 // Destruct the elements of the array in reverse order
540 element_type *pN = static_cast<element_type *>(ptr()) + d_size - 1;
541 for (size_t i = 0; i < d_size; ++i, --pN) {
542 ElementTraits::destroy(elementAlloc, pN);
543 }
544}
545
546template <class TYPE, class ALLOCATOR>
547inline
549{
551 template rebind_traits<char> CharATraits;
552 typename CharATraits::allocator_type charAlloc(d_allocator);
553
554 this->d_allocator.~ReboundAllocator();
555 CharATraits::deallocate(charAlloc, d_allocated_ptr_p, alloc_size(d_size));
556}
557
558template <class TYPE, class ALLOCATOR>
559inline
560void *
562::getDeleter(const std::type_info&)
563{
564 return 0;
565}
566
567template <class TYPE, class ALLOCATOR>
568inline
569const typename
573{
574 return reinterpret_cast<const element_type *>(
575 reinterpret_cast<const char *>(this) + offset_of_first_element());
576}
577
578template <class TYPE, class ALLOCATOR>
579inline typename
582{
583 return get_pointer_to_first_element();
584}
585
586// ACCESSORS
587template <class TYPE, class ALLOCATOR>
588inline
589void *
591{
592 return const_cast<void *>(
593 static_cast<const void *>(
594 get_pointer_to_first_element()));
595}
596
597} // close package namespace
598
599// ============================================================================
600// TYPE TRAITS
601// ============================================================================
602
603namespace bslma {
604
605template <class TYPE, class ALLOCATOR>
606struct UsesBslmaAllocator< bslstl::SharedPtrAllocateInplaceRep<TYPE,
607 ALLOCATOR> >
609{};
610
611template <class TYPE, class ALLOCATOR>
613 bslstl::SharedPtrArrayAllocateInplaceRep<TYPE, ALLOCATOR> >
615{};
616
617} // close namespace bslma
618
619
620#endif
621
622// ----------------------------------------------------------------------------
623// Copyright 2014 Bloomberg Finance L.P.
624//
625// Licensed under the Apache License, Version 2.0 (the "License");
626// you may not use this file except in compliance with the License.
627// You may obtain a copy of the License at
628//
629// http://www.apache.org/licenses/LICENSE-2.0
630//
631// Unless required by applicable law or agreed to in writing, software
632// distributed under the License is distributed on an "AS IS" BASIS,
633// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
634// See the License for the specific language governing permissions and
635// limitations under the License.
636// ----------------------------- END-OF-FILE ----------------------------------
637
638/** @} */
639/** @} */
640/** @} */
Definition bslstl_sharedptrallocateinplacerep.h:111
static SharedPtrAllocateInplaceRep * makeRep(ReboundAllocator basicAllocator)
Definition bslstl_sharedptrallocateinplacerep.h:368
void * getDeleter(const std::type_info &type) BSLS_KEYWORD_OVERRIDE
Definition bslstl_sharedptrallocateinplacerep.h:397
ReboundTraits::allocator_type ReboundAllocator
Definition bslstl_sharedptrallocateinplacerep.h:120
TYPE * ptr()
Definition bslstl_sharedptrallocateinplacerep.h:404
void * originalPtr() const BSLS_KEYWORD_OVERRIDE
Definition bslstl_sharedptrallocateinplacerep.h:413
void disposeRep() BSLS_KEYWORD_OVERRIDE
Definition bslstl_sharedptrallocateinplacerep.h:387
void disposeObject() BSLS_KEYWORD_OVERRIDE
Definition bslstl_sharedptrallocateinplacerep.h:380
Definition bslstl_sharedptrallocateinplacerep.h:216
void disposeObject() BSLS_KEYWORD_OVERRIDE
Definition bslstl_sharedptrallocateinplacerep.h:532
element_type * ptr()
Definition bslstl_sharedptrallocateinplacerep.h:581
bsl::remove_extent< TYPE >::type element_type
Definition bslstl_sharedptrallocateinplacerep.h:226
ReboundTraits::allocator_type ReboundAllocator
Definition bslstl_sharedptrallocateinplacerep.h:227
void * originalPtr() const BSLS_KEYWORD_OVERRIDE
Definition bslstl_sharedptrallocateinplacerep.h:590
static size_t alloc_size(size_t numElements)
Definition bslstl_sharedptrallocateinplacerep.h:469
static SharedPtrArrayAllocateInplaceRep * makeRep(ReboundAllocator basicAllocator, size_t numElements)
Definition bslstl_sharedptrallocateinplacerep.h:483
void disposeRep() BSLS_KEYWORD_OVERRIDE
Definition bslstl_sharedptrallocateinplacerep.h:548
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:229
#define BSLS_ASSERT_OPT(X)
Definition bsls_assert.h:1856
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_OVERRIDE
Definition bsls_keyword.h:653
Definition balxml_encoderoptions.h:68
Definition bslstl_algorithm.h:82
Definition bdldfp_decimal.h:5188
Definition bslma_allocatortraits.h:1061
Definition bslmf_integralconstant.h:244
Definition bslmf_isarray.h:168
t_TYPE type
Definition bslmf_removeextent.h:132
Definition bslma_usesbslmaallocator.h:343
Definition bsls_alignmentfromtype.h:376
@ BSLS_MAX_ALIGNMENT
Definition bsls_alignmentutil.h:275
std::size_t UintPtr
Definition bsls_types.h:126
Definition bsls_objectbuffer.h:276
TYPE * address()
Definition bsls_objectbuffer.h:334