BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslstl_sharedptrallocateoutofplacerep.h
Go to the documentation of this file.
1/// @file bslstl_sharedptrallocateoutofplacerep.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslstl_sharedptrallocateoutofplacerep.h -*-C++-*-
8#ifndef INCLUDED_BSLSTL_SHAREDPTRALLOCATEOUTOFPLACEREP
9#define INCLUDED_BSLSTL_SHAREDPTRALLOCATEOUTOFPLACEREP
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id$ $CSID$")
13
14/// @defgroup bslstl_sharedptrallocateoutofplacerep bslstl_sharedptrallocateoutofplacerep
15/// @brief Provide an out-of-place implementation of `bslma::SharedPtrRep`.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslstl
19/// @{
20/// @addtogroup bslstl_sharedptrallocateoutofplacerep
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslstl_sharedptrallocateoutofplacerep-purpose"> Purpose</a>
25/// * <a href="#bslstl_sharedptrallocateoutofplacerep-classes"> Classes </a>
26/// * <a href="#bslstl_sharedptrallocateoutofplacerep-description"> Description </a>
27/// * <a href="#bslstl_sharedptrallocateoutofplacerep-thread-safety"> Thread Safety </a>
28/// * <a href="#bslstl_sharedptrallocateoutofplacerep-deleters"> Deleters </a>
29/// * <a href="#bslstl_sharedptrallocateoutofplacerep-usage"> Usage </a>
30///
31/// # Purpose {#bslstl_sharedptrallocateoutofplacerep-purpose}
32/// Provide an out-of-place implementation of `bslma::SharedPtrRep`.
33///
34/// # Classes {#bslstl_sharedptrallocateoutofplacerep-classes}
35///
36/// - bslstl::SharedPtrAllocateOutofplaceRep: out-of-place `shared_ptr` imp.
37///
38/// @see bslma_sharedptrrep, bslma_sharedptroutofplacerep, bslstl_sharedptr
39///
40/// # Description {#bslstl_sharedptrallocateoutofplacerep-description}
41/// This component provides a class template,
42/// `bslstl::SharedPtrAllocateOutofplaceRep` , which is a concrete
43/// implementation of `bslma::SharedPtrRep` for managing objects of the
44/// parameterized `TYPE` that are stored outside of the representation. When
45/// all references to the out-of-place object are released using `releaseRef`,
46/// the deleter of the parameterized `DELETER` type is invoked to delete the
47/// shared object. Memory is supplied and reclaimed by an allocator of the
48/// parameterized `ALLOCATOR` type.
49///
50/// ## Thread Safety {#bslstl_sharedptrallocateoutofplacerep-thread-safety}
51///
52///
53/// `bslstl::SharedPtrAllocateOutofplaceRep` is thread-safe provided that
54/// `disposeObject` and `disposeRep` are not called explicitly, meaning that all
55/// non-creator operations other than `disposeObject` and `disposeRep` on a
56/// given instance can be safely invoked simultaneously from multiple threads
57/// (`disposeObject` and `disposeRep` are meant to be invoked only by
58/// `releaseRef` and `releaseWeakRef`). Note that there is no thread safety
59/// guarantees for operations on the managed object.
60///
61/// ## Deleters {#bslstl_sharedptrallocateoutofplacerep-deleters}
62///
63///
64/// When the last shared reference to a shared object is released, the object is
65/// destroyed using the "deleter" provided when the associated shared pointer
66/// representation was created. `bslstl::SharedPtrAllocateOutofplaceRep`
67/// supports two kinds of "deleter" objects, which vary in how they are invoked.
68/// A "function-like" deleter is any language entity that can be invoked such
69/// that the expression `deleterInstance(objectPtr)` is a valid expression, and
70/// a "factory" deleter is any language entity that can be invoked such that the
71/// expression `deleterInstance.deleteObject(objectPtr)` is a valid expression,
72/// where `deleterInstance` is an instance of the "deleter" object, and
73/// `objectPtr` is a pointer to the shared object. In summary:
74/// @code
75/// Deleter Expression used to destroy `objectPtr`
76/// - - - - - - - - - - - - - - - - - - - - - - - - - - -
77/// "function-like" deleterInstance(objectPtr);
78/// "factory" deleterInstance.deleteObject(objectPtr);
79/// @endcode
80/// The following are examples of function-like deleters that delete an object
81/// of `MyType`:
82/// @code
83/// /// Delete the specified `object`.
84/// void deleteObject(MyType *object);
85///
86/// /// Release the specified `object`.
87/// void releaseObject(MyType *object);
88///
89/// /// This `struct` provides an `operator()` that can be used to delete a
90/// /// `MyType` object.
91/// struct FunctionLikeDeleterObject {
92///
93/// /// Destroy the specified `object`.
94/// void operator()(MyType *object);
95/// };
96/// @endcode
97/// The following on the other hand is an example of a factory deleter:
98/// @code
99/// class MyFactory {
100///
101/// // . . .
102///
103/// // MANIPULATORS
104///
105/// /// Create a `MyType` object. Optionally specify a `basicAllocator`
106/// /// used to supply memory. If `basicAllocator` is 0, the currently
107/// /// installed default allocator is used.
108/// MyType *createObject(bslma::Allocator *basicAllocator = 0);
109///
110/// /// Delete the specified `object`.
111/// void deleteObject(MyType *object);
112/// };
113/// @endcode
114/// Note that `deleteObject` is provided by all `bslma` allocators and by any
115/// object that implements the `bdlma::Deleter` protocol. Thus, any of these
116/// objects can be used as a factory deleter. The purpose of this design is to
117/// allow `bslma` allocators and factories to be used seamlessly as deleters.
118///
119/// The selection of which expression is used by
120/// `bslstl::SharedPtrAllocateOutofplaceRep` to destroy a shared object is based
121/// on how the deleter is passed to the shared pointer object: Deleters that are
122/// passed by *address* are assumed to be factory deleters, while those that are
123/// passed by *value* are assumed to be function-like. Note that if the wrong
124/// interface is used for a deleter, i.e., if a function-like deleter is passed
125/// by pointer, or a factory deleter is passed by value, and the expression used
126/// to delete the object is invalid, a compiler diagnostic will be emitted
127/// indicating the error.
128///
129/// ## Usage {#bslstl_sharedptrallocateoutofplacerep-usage}
130///
131///
132/// The following example demonstrates how to implement a shared
133/// `bdlt::Datetime` object using `bslstl::SharedPtrAllocateOutofplaceRep`:
134/// @code
135/// /// This class provide a reference counted smart pointer to support
136/// /// shared ownership of a `bdlt::Datetime` object.
137/// class MySharedDatetimePtr {
138///
139/// private:
140/// bdlt::Datetime *d_ptr_p; // pointer to the managed object
141/// bslma::SharedPtrRep *d_rep_p; // pointer to the representation object
142///
143/// private:
144/// // NOT IMPLEMENTED
145/// MySharedDatetimePtr& operator=(const MySharedDatetimePtr&);
146///
147/// public:
148/// // CREATORS
149///
150/// /// Create a `MySharedDatetimePtr` object to managed the specified
151/// /// `ptr`. Optionally specify an `basicAllocator` to allocate and
152/// /// deallocate the internal representation and to destroy `ptr` when
153/// /// all references have been released. The behavior is undefined
154/// /// unless `ptr` was allocated using memory supplied by
155/// /// `basicAllocator`.
156/// MySharedDatetimePtr(bdlt::Datetime *ptr,
157/// bslma::Allocator *basicAllocator = 0);
158///
159/// /// Create a shared datetime that refers to the same object managed
160/// /// by the specified `original`
161/// MySharedDatetimePtr(const MySharedDatetimePtr& original);
162///
163/// /// Destroy this shared datetime and release the reference to the
164/// /// `bdlt::Datetime` object to which it might be referring. If this
165/// /// is the last shared reference, deleted the managed object.
166/// ~MySharedDatetimePtr();
167///
168/// // MANIPULATORS
169///
170/// /// Return a reference offering modifiable access to the shared
171/// /// datetime.
172/// bdlt::Datetime& operator*() const;
173///
174/// /// Return the address of the modifiable `bdlt::Datetime` to which
175/// /// this object refers.
176/// bdlt::Datetime *operator->() const;
177///
178/// /// Return the address of the modifiable `bdlt::Datetime` to which
179/// /// this object refers.
180/// bdlt::Datetime *ptr() const;
181/// };
182/// @endcode
183/// Finally, we define the implementation.
184/// @code
185/// MySharedDatetimePtr::MySharedDatetimePtr(bdlt::Datetime *ptr,
186/// bslma::Allocator *basicAllocator)
187/// {
188/// d_ptr_p = ptr;
189/// d_rep_p = bslstl::SharedPtrAllocateOutofplaceRep<bdlt::Datetime,
190/// bslma::Allocator *>::
191/// makeOutofplaceRep(ptr, basicAllocator, basicAllocator);
192/// }
193///
194/// MySharedDatetimePtr::MySharedDatetimePtr(
195/// const MySharedDatetimePtr& original)
196/// : d_ptr_p(original.d_ptr_p)
197/// , d_rep_p(original.d_rep_p)
198/// {
199/// if (d_ptr_p) {
200/// d_rep_p->acquireRef();
201/// } else {
202/// d_rep_p = 0;
203/// }
204/// }
205///
206/// MySharedDatetimePtr::~MySharedDatetimePtr()
207/// {
208/// if (d_rep_p) {
209/// d_rep_p->releaseRef();
210/// }
211/// }
212///
213/// bdlt::Datetime& MySharedDatetimePtr::operator*() const {
214/// return *d_ptr_p;
215/// }
216///
217/// bdlt::Datetime *MySharedDatetimePtr::operator->() const {
218/// return d_ptr_p;
219/// }
220///
221/// bdlt::Datetime *MySharedDatetimePtr::ptr() const {
222/// return d_ptr_p;
223/// }
224/// @endcode
225/// @}
226/** @} */
227/** @} */
228
229/** @addtogroup bsl
230 * @{
231 */
232/** @addtogroup bslstl
233 * @{
234 */
235/** @addtogroup bslstl_sharedptrallocateoutofplacerep
236 * @{
237 */
238
239#include <bslscm_version.h>
240
242#include <bslma_pointerutil.h>
243#include <bslma_sharedptrrep.h>
244
245#include <bsls_keyword.h>
246#include <bsls_util.h>
247
248#include <typeinfo>
249
250
251namespace bslstl {
252
253 // ====================================
254 // class SharedPtrAllocateOutofplaceRep
255 // ====================================
256
257/// This class provides a concrete implementation of the `SharedPtrRep`
258/// protocol for out-of-place instances of the parameterized `TYPE`. Upon
259/// destruction of this object, the parameterized `DELETER` type is invoked
260/// on the pointer to the shared object.
261template <class TYPE, class DELETER, class ALLOCATOR>
262class SharedPtrAllocateOutofplaceRep : public BloombergLP::bslma::SharedPtrRep
263 {
264
265 // PRIVATE TYPES
267
268 typedef typename
269 OriginalTraits::template rebind_traits<SharedPtrAllocateOutofplaceRep>
270 AllocatorTraits;
271 typedef typename AllocatorTraits::allocator_type Allocator;
272
273 // DATA
274 TYPE *d_ptr_p; // pointer to out-of-place object (held, not owned)
275 DELETER d_deleter; // deleter for this out-of-place instance
276 Allocator d_allocator; // copy of the allocator for this instance
277
278 private:
279 // NOT IMPLEMENTED
283
284 // PRIVATE CREATORS
285
286 /// Create a `SharedPtrAllocateOutofplaceRep` that manages the lifetime
287 /// of the specified `ptr`, using the specified `deleter` to destroy
288 /// `ptr`, and using the specified `basicAllocator` to supply memory.
289 ///
290 /// \note Note that `basicAllocator` will be used to destroy this
291 /// representation object, but not necessarily to destroy `ptr`. Also
292 /// note that a `SharedPtrAllocateOutofplaceRep` must be created using
293 /// `makeOutofplaceRep`, which will call the private constructor.
295 const DELETER& deleter,
296 const ALLOCATOR& basicAllocator);
297
298 /// Destroy this representation object and if the shared object has not
299 /// been deleted, delete the shared object using the associated deleter.
300 ///
301 /// \note Note that this destructor is never called explicitly. Instead,
302 /// `disposeObject` destroys the shared object and `disposeRep`
303 /// deallocates this representation object.
305
306 public:
307 // CLASS METHODS
308
309 /// Return the address of a newly created
310 /// `SharedPtrAllocateOutofplaceRep` object that manages the lifetime of
311 /// the specified `ptr`, uses the specified `deleter` to destroy `ptr`,
312 /// and uses the specified `basicAllocator` to supply memory.
313 ///
314 /// \note Note that the parameterized `DELETER` type will be used to deallocate the
315 /// memory pointed to by `ptr`.
317 TYPE *ptr,
318 const DELETER& deleter,
319 const ALLOCATOR& basicAllocator);
320
321 // MANIPULATORS
322
323 /// Destroy the object referred to by this representation. This method
324 /// is invoked by `releaseRef` when the number of shared references
325 /// reaches zero and should not be explicitly invoked otherwise.
327
328 /// Destroy this representation object and deallocate the associated
329 /// memory. This method is invoked by `releaseRef` and `releaseWeakRef`
330 /// when the number of weak references and the number of shared
331 /// references both reach zero and should not be explicitly invoked otherwise.
332 ///
333 /// \pre The behavior is undefined unless `disposeObject` has already been called for this representation.
334 ///
335 /// \note Note that this method
336 /// effectively serves as the representation object's destructor.
338
339 /// Return a pointer to the deleter stored by the derived representation
340 /// if the deleter has the same type as that described by the specified
341 /// `type`, and a null pointer otherwise.
342 void *getDeleter(const std::type_info& type) BSLS_KEYWORD_OVERRIDE;
343
344 // ACCESSORS
345
346 /// Return the (untyped) address of the modifiable shared object to
347 /// which this object refers.
349
350 /// Return the address of the modifiable shared object to which this
351 /// object refers.
352 TYPE *ptr() const;
353};
354
355 // =================================================
356 // struct SharedPtrAllocateOutofplaceRep_InitProctor
357 // =================================================
358
359/// This proctor is used for out-of-place shared pointer instantiations.
360/// Generally, a proctor is created prior to constructing a
361/// `SharedPtrAllocateOutofplaceRep` and released after successful
362/// construction. In the event that an exception is thrown during
363/// construction of the representation, the proctor will delete the provided pointer using the provided deleter.
364///
365/// \note Note that the provided deleter is
366/// held by reference and must remain valid for the lifetime of the proctor.
367/// If the proctor is not released before it's destruction, a copy of the
368/// deleter is instantiated to delete the pointer (in case `operator()` is
369/// non-`const`). Also note that if the deleter throws during
370/// copy construction, the provided pointer will not be destroyed.
371///
372/// See @ref bslstl_sharedptrallocateoutofplacerep
373template <class TYPE, class DELETER>
375
376 // DATA
377 TYPE *d_ptr_p; // address of the managed object (held, not
378 // owned)
379
380 const DELETER& d_deleter; // deleter used to destroy managed object
381
382 private:
383 // NOT IMPLEMENTED
388
389 public:
390 // CREATORS
391
392 /// Create a proctor managing the specified `ptr` and using the
393 /// specified `deleter` to destroy `ptr` when the proctor is destroyed,
394 /// unless it has been released from management by a call to `release`.
396 const DELETER& deleter);
397
398 /// Destroy this proctor and the object (if any) managed by this
399 /// proctor.
401
402 // MANIPULATORS
403
404 /// Release from management the object referred to by this proctor.
405 void release();
406};
407
408// ============================================================================
409// INLINE DEFINITIONS
410// ============================================================================
411
412 // ------------------------------------
413 // class SharedPtrAllocateOutofplaceRep
414 // ------------------------------------
415
416// PRIVATE CREATORS
417template <class TYPE, class DELETER, class ALLOCATOR>
418inline
421 const DELETER& deleter,
422 const ALLOCATOR& basicAllocator)
423: d_ptr_p(ptr)
424, d_deleter(deleter)
425, d_allocator(basicAllocator)
426{
427}
428
429template <class TYPE, class DELETER, class ALLOCATOR>
430inline
431SharedPtrAllocateOutofplaceRep<TYPE, DELETER, ALLOCATOR>::
432~SharedPtrAllocateOutofplaceRep()
433{
434}
435
436// CLASS METHODS
437template <class TYPE, class DELETER, class ALLOCATOR>
438SharedPtrAllocateOutofplaceRep<TYPE, DELETER, ALLOCATOR> *
440 TYPE *ptr,
441 const DELETER& deleter,
442 const ALLOCATOR& basicAllocator)
443{
445 deleter);
446
447 Allocator alloc(basicAllocator);
448
449 SharedPtrAllocateOutofplaceRep *rep = AllocatorTraits::allocate(alloc, 1);
450 new (rep) SharedPtrAllocateOutofplaceRep(ptr, deleter, alloc);
451
452 proctor.release();
453
454 return rep;
455}
456
457// MANIPULATORS
458template <class TYPE, class DELETER, class ALLOCATOR>
459inline
461{
462 d_deleter(d_ptr_p);
463 d_ptr_p = 0;
464}
465
466template <class TYPE, class DELETER, class ALLOCATOR>
467inline
469{
470 Allocator alloc(d_allocator);
472 AllocatorTraits::deallocate(alloc, this, 1);
473}
474
475template <class TYPE, class DELETER, class ALLOCATOR>
476inline
477void *
479 const std::type_info& type)
480{
481 return typeid(d_deleter) == type
482 ? bsls::Util::addressOf(d_deleter)
483 : 0;
484}
485
486// ACCESSORS
487template <class TYPE, class DELETER, class ALLOCATOR>
488inline
489void *
494
495template <class TYPE, class DELETER, class ALLOCATOR>
496inline
498{
499 return d_ptr_p;
500}
501
502 // ------------------------------------------
503 // SharedPtrAllocateOutofplaceRep_InitProctor
504 // ------------------------------------------
505
506// CREATORS
507template <class TYPE, class DELETER>
508inline
511 const DELETER& deleter)
512: d_ptr_p(ptr)
513, d_deleter(deleter)
514{
515}
516
517template <class TYPE, class DELETER>
518inline
521{
522 // The proctor must destroy 'd_ptr_p' to avoid a leak, but is not subject
523 // to the reference-counting of null pointers principle, where the deleter
524 // is called on destroying the last reference, even if 'd_ptr_p' is null.
525
526 if (d_ptr_p) {
527 d_deleter(d_ptr_p);
528 }
529}
530
531// MANIPULATORS
532template <class TYPE, class DELETER>
533inline
538
539} // close package namespace
540
541
542#endif
543
544// ----------------------------------------------------------------------------
545// Copyright 2014 Bloomberg Finance L.P.
546//
547// Licensed under the Apache License, Version 2.0 (the "License");
548// you may not use this file except in compliance with the License.
549// You may obtain a copy of the License at
550//
551// http://www.apache.org/licenses/LICENSE-2.0
552//
553// Unless required by applicable law or agreed to in writing, software
554// distributed under the License is distributed on an "AS IS" BASIS,
555// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
556// See the License for the specific language governing permissions and
557// limitations under the License.
558// ----------------------------- END-OF-FILE ----------------------------------
559
560/** @} */
561/** @} */
562/** @} */
Definition bslstl_sharedptrallocateoutofplacerep.h:374
~SharedPtrAllocateOutofplaceRep_InitProctor()
Definition bslstl_sharedptrallocateoutofplacerep.h:520
void release()
Release from management the object referred to by this proctor.
Definition bslstl_sharedptrallocateoutofplacerep.h:534
Definition bslstl_sharedptrallocateoutofplacerep.h:263
void disposeRep() BSLS_KEYWORD_OVERRIDE
Definition bslstl_sharedptrallocateoutofplacerep.h:468
void disposeObject() BSLS_KEYWORD_OVERRIDE
Definition bslstl_sharedptrallocateoutofplacerep.h:460
void * originalPtr() const BSLS_KEYWORD_OVERRIDE
Definition bslstl_sharedptrallocateoutofplacerep.h:490
TYPE * ptr() const
Definition bslstl_sharedptrallocateoutofplacerep.h:497
void * getDeleter(const std::type_info &type) BSLS_KEYWORD_OVERRIDE
Definition bslstl_sharedptrallocateoutofplacerep.h:478
static SharedPtrAllocateOutofplaceRep * makeOutofplaceRep(TYPE *ptr, const DELETER &deleter, const ALLOCATOR &basicAllocator)
Definition bslstl_sharedptrallocateoutofplacerep.h:439
#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 bslstl_algorithm.h:84
Definition bslma_allocatortraits.h:1089
static BSLS_KEYWORD_CONSTEXPR void * voidify(TYPE *address) BSLS_KEYWORD_NOEXCEPT
Definition bslma_pointerutil.h:350
static TYPE * addressOf(TYPE &obj)
Definition bsls_util.h:312