BDE 4.14.0 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_sharedptrrep.h>
243
244#include <bsls_keyword.h>
245#include <bsls_util.h>
246
247#include <typeinfo>
248
249
250namespace bslstl {
251
252 // ====================================
253 // class SharedPtrAllocateOutofplaceRep
254 // ====================================
255
256/// This class provides a concrete implementation of the `SharedPtrRep`
257/// protocol for out-of-place instances of the parameterized `TYPE`. Upon
258/// destruction of this object, the parameterized `DELETER` type is invoked
259/// on the pointer to the shared object.
260template <class TYPE, class DELETER, class ALLOCATOR>
261class SharedPtrAllocateOutofplaceRep : public BloombergLP::bslma::SharedPtrRep
262 {
263
264 // PRIVATE TYPES
266
267 typedef typename
268 OriginalTraits::template rebind_traits<SharedPtrAllocateOutofplaceRep>
269 AllocatorTraits;
270 typedef typename AllocatorTraits::allocator_type Allocator;
271
272 // DATA
273 TYPE *d_ptr_p; // pointer to out-of-place object (held, not owned)
274 DELETER d_deleter; // deleter for this out-of-place instance
275 Allocator d_allocator; // copy of the allocator for this instance
276
277 private:
278 // NOT IMPLEMENTED
282
283 // PRIVATE CREATORS
284
285 /// Create a `SharedPtrAllocateOutofplaceRep` that manages the lifetime
286 /// of the specified `ptr`, using the specified `deleter` to destroy
287 /// `ptr`, and using the specified `basicAllocator` to supply memory.
288 /// Note that `basicAllocator` will be used to destroy this
289 /// representation object, but not necessarily to destroy `ptr`. Also
290 /// note that a `SharedPtrAllocateOutofplaceRep` must be created using
291 /// `makeOutofplaceRep`, which will call the private constructor.
293 const DELETER& deleter,
294 const ALLOCATOR& basicAllocator);
295
296 /// Destroy this representation object and if the shared object has not
297 /// been deleted, delete the shared object using the associated deleter.
298 /// Note that this destructor is never called explicitly. Instead,
299 /// `disposeObject` destroys the shared object and `disposeRep`
300 /// deallocates this representation object.
302
303 public:
304 // CLASS METHODS
305
306 /// Return the address of a newly created
307 /// `SharedPtrAllocateOutofplaceRep` object that manages the lifetime of
308 /// the specified `ptr`, uses the specified `deleter` to destroy `ptr`,
309 /// and uses the specified `basicAllocator` to supply memory. Note that
310 /// the parameterized `DELETER` type will be used to deallocate the
311 /// memory pointed to by `ptr`.
313 TYPE *ptr,
314 const DELETER& deleter,
315 const ALLOCATOR& basicAllocator);
316
317 // MANIPULATORS
318
319 /// Destroy the object referred to by this representation. This method
320 /// is invoked by `releaseRef` when the number of shared references
321 /// reaches zero and should not be explicitly invoked otherwise.
323
324 /// Destroy this representation object and deallocate the associated
325 /// memory. This method is invoked by `releaseRef` and `releaseWeakRef`
326 /// when the number of weak references and the number of shared
327 /// references both reach zero and should not be explicitly invoked
328 /// otherwise. The behavior is undefined unless `disposeObject` has
329 /// already been called for this representation. Note that this method
330 /// effectively serves as the representation object's destructor.
332
333 /// Return a pointer to the deleter stored by the derived representation
334 /// if the deleter has the same type as that described by the specified
335 /// `type`, and a null pointer otherwise.
336 void *getDeleter(const std::type_info& type) BSLS_KEYWORD_OVERRIDE;
337
338 // ACCESSORS
339
340 /// Return the (untyped) address of the modifiable shared object to
341 /// which this object refers.
343
344 /// Return the address of the modifiable shared object to which this
345 /// object refers.
346 TYPE *ptr() const;
347};
348
349 // =================================================
350 // struct SharedPtrAllocateOutofplaceRep_InitProctor
351 // =================================================
352
353/// This proctor is used for out-of-place shared pointer instantiations.
354/// Generally, a proctor is created prior to constructing a
355/// `SharedPtrAllocateOutofplaceRep` and released after successful
356/// construction. In the event that an exception is thrown during
357/// construction of the representation, the proctor will delete the provided
358/// pointer using the provided deleter. Note that the provided deleter is
359/// held by reference and must remain valid for the lifetime of the proctor.
360/// If the proctor is not released before it's destruction, a copy of the
361/// deleter is instantiated to delete the pointer (in case `operator()` is
362/// non-`const`). Also note that if the deleter throws during
363/// copy construction, the provided pointer will not be destroyed.
364///
365/// See @ref bslstl_sharedptrallocateoutofplacerep
366template <class TYPE, class DELETER>
368
369 // DATA
370 TYPE *d_ptr_p; // address of the managed object (held, not
371 // owned)
372
373 const DELETER& d_deleter; // deleter used to destroy managed object
374
375 private:
376 // NOT IMPLEMENTED
381
382 public:
383 // CREATORS
384
385 /// Create a proctor managing the specified `ptr` and using the
386 /// specified `deleter` to destroy `ptr` when the proctor is destroyed,
387 /// unless it has been released from management by a call to `release`.
389 const DELETER& deleter);
390
391 /// Destroy this proctor and the object (if any) managed by this
392 /// proctor.
394
395 // MANIPULATORS
396
397 /// Release from management the object referred to by this proctor.
398 void release();
399};
400
401// ============================================================================
402// INLINE DEFINITIONS
403// ============================================================================
404
405 // ------------------------------------
406 // class SharedPtrAllocateOutofplaceRep
407 // ------------------------------------
408
409// PRIVATE CREATORS
410template <class TYPE, class DELETER, class ALLOCATOR>
411inline
414 const DELETER& deleter,
415 const ALLOCATOR& basicAllocator)
416: d_ptr_p(ptr)
417, d_deleter(deleter)
418, d_allocator(basicAllocator)
419{
420}
421
422template <class TYPE, class DELETER, class ALLOCATOR>
423inline
424SharedPtrAllocateOutofplaceRep<TYPE, DELETER, ALLOCATOR>::
425~SharedPtrAllocateOutofplaceRep()
426{
427}
428
429// CLASS METHODS
430template <class TYPE, class DELETER, class ALLOCATOR>
431SharedPtrAllocateOutofplaceRep<TYPE, DELETER, ALLOCATOR> *
433 TYPE *ptr,
434 const DELETER& deleter,
435 const ALLOCATOR& basicAllocator)
436{
438 deleter);
439
440 Allocator alloc(basicAllocator);
441
442 SharedPtrAllocateOutofplaceRep *rep = AllocatorTraits::allocate(alloc, 1);
443 new (rep) SharedPtrAllocateOutofplaceRep(ptr, deleter, alloc);
444
445 proctor.release();
446
447 return rep;
448}
449
450// MANIPULATORS
451template <class TYPE, class DELETER, class ALLOCATOR>
452inline
454{
455 d_deleter(d_ptr_p);
456 d_ptr_p = 0;
457}
458
459template <class TYPE, class DELETER, class ALLOCATOR>
460inline
462{
463 Allocator alloc(d_allocator);
465 AllocatorTraits::deallocate(alloc, this, 1);
466}
467
468template <class TYPE, class DELETER, class ALLOCATOR>
469inline
470void *
472 const std::type_info& type)
473{
474 return typeid(d_deleter) == type
475 ? bsls::Util::addressOf(d_deleter)
476 : 0;
477}
478
479// ACCESSORS
480template <class TYPE, class DELETER, class ALLOCATOR>
481inline
482void *
484{
485 return const_cast<void *>(static_cast<const void *>(d_ptr_p));
486}
487
488template <class TYPE, class DELETER, class ALLOCATOR>
489inline
491{
492 return d_ptr_p;
493}
494
495 // ------------------------------------------
496 // SharedPtrAllocateOutofplaceRep_InitProctor
497 // ------------------------------------------
498
499// CREATORS
500template <class TYPE, class DELETER>
501inline
504 const DELETER& deleter)
505: d_ptr_p(ptr)
506, d_deleter(deleter)
507{
508}
509
510template <class TYPE, class DELETER>
511inline
514{
515 // The proctor must destroy 'd_ptr_p' to avoid a leak, but is not subject
516 // to the reference-counting of null pointers principle, where the deleter
517 // is called on destroying the last reference, even if 'd_ptr_p' is null.
518
519 if (d_ptr_p) {
520 d_deleter(d_ptr_p);
521 }
522}
523
524// MANIPULATORS
525template <class TYPE, class DELETER>
526inline
531
532} // close package namespace
533
534
535#endif
536
537// ----------------------------------------------------------------------------
538// Copyright 2014 Bloomberg Finance L.P.
539//
540// Licensed under the Apache License, Version 2.0 (the "License");
541// you may not use this file except in compliance with the License.
542// You may obtain a copy of the License at
543//
544// http://www.apache.org/licenses/LICENSE-2.0
545//
546// Unless required by applicable law or agreed to in writing, software
547// distributed under the License is distributed on an "AS IS" BASIS,
548// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
549// See the License for the specific language governing permissions and
550// limitations under the License.
551// ----------------------------- END-OF-FILE ----------------------------------
552
553/** @} */
554/** @} */
555/** @} */
Definition bslstl_sharedptrallocateoutofplacerep.h:367
~SharedPtrAllocateOutofplaceRep_InitProctor()
Definition bslstl_sharedptrallocateoutofplacerep.h:513
void release()
Release from management the object referred to by this proctor.
Definition bslstl_sharedptrallocateoutofplacerep.h:527
Definition bslstl_sharedptrallocateoutofplacerep.h:262
void disposeRep() BSLS_KEYWORD_OVERRIDE
Definition bslstl_sharedptrallocateoutofplacerep.h:461
void disposeObject() BSLS_KEYWORD_OVERRIDE
Definition bslstl_sharedptrallocateoutofplacerep.h:453
void * originalPtr() const BSLS_KEYWORD_OVERRIDE
Definition bslstl_sharedptrallocateoutofplacerep.h:483
TYPE * ptr() const
Definition bslstl_sharedptrallocateoutofplacerep.h:490
void * getDeleter(const std::type_info &type) BSLS_KEYWORD_OVERRIDE
Definition bslstl_sharedptrallocateoutofplacerep.h:471
static SharedPtrAllocateOutofplaceRep * makeOutofplaceRep(TYPE *ptr, const DELETER &deleter, const ALLOCATOR &basicAllocator)
Definition bslstl_sharedptrallocateoutofplacerep.h:432
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_OVERRIDE
Definition bsls_keyword.h:653
Definition bslstl_algorithm.h:82
Definition bslma_allocatortraits.h:1061
static TYPE * addressOf(TYPE &obj)
Definition bsls_util.h:305