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