BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslma_sharedptrrep.h
Go to the documentation of this file.
1/// @file bslma_sharedptrrep.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslma_sharedptrrep.h -*-C++-*-
8#ifndef INCLUDED_BSLMA_SHAREDPTRREP
9#define INCLUDED_BSLMA_SHAREDPTRREP
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id$ $CSID$")
13
14/// @defgroup bslma_sharedptrrep bslma_sharedptrrep
15/// @brief Provide an abstract class for a shared object manager.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslma
19/// @{
20/// @addtogroup bslma_sharedptrrep
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslma_sharedptrrep-purpose"> Purpose</a>
25/// * <a href="#bslma_sharedptrrep-classes"> Classes </a>
26/// * <a href="#bslma_sharedptrrep-description"> Description </a>
27/// * <a href="#bslma_sharedptrrep-shared-and-weak-references"> Shared and Weak References </a>
28/// * <a href="#bslma_sharedptrrep-thread-safety"> Thread Safety </a>
29/// * <a href="#bslma_sharedptrrep-disposeobject-and-disposerep"> disposeObject and disposeRep </a>
30/// * <a href="#bslma_sharedptrrep-usage"> Usage </a>
31///
32/// # Purpose {#bslma_sharedptrrep-purpose}
33/// Provide an abstract class for a shared object manager.
34///
35/// # Classes {#bslma_sharedptrrep-classes}
36///
37/// - bslma::SharedPtrRep : shared pointer representation abstract class
38///
39/// @see bslstl_sharedptr, bslma_sharedptrrep_inplace,
40/// bslma_sharedptrrep_outofplace
41///
42/// # Description {#bslma_sharedptrrep-description}
43/// This component provides a partially implemented abstract class,
44/// `bslma::SharedPtrRep`, for managing the lifetime of a shared object.
45/// `bslma::SharedPtrRep` provides a count of both shared and weak references to
46/// a shared object (described in more detail in the next section). In
47/// addition, `bslma::SharedPtrRep` provides protocol methods that allows a
48/// concrete implementation to specify what action should be taken when these
49/// reference counts reach zero.
50///
51/// ## Shared and Weak References {#bslma_sharedptrrep-shared-and-weak-references}
52///
53///
54/// There are two types of references to shared objects:
55///
56/// 1) A shared reference allows users to share the ownership of an object and
57/// control its lifetime. A shared object is destroyed only when the last
58/// shared reference to it is released. The function `acquireRef` should be
59/// called when a new shared reference is created and `releaseRef` should be
60/// called when a share reference is removed.
61///
62/// 2) A weak reference provides users conditional access to an object without
63/// sharing its ownership (or affecting its lifetime). A shared object can be
64/// destroyed even if there are weak references to it. The function
65/// `acquireWeakRef` should be called when a new weak reference is created and
66/// `releaseWeakRef` should be called when a weak reference is removed.
67///
68/// ## Thread Safety {#bslma_sharedptrrep-thread-safety}
69///
70///
71/// `bslma::SharedPtrRep` is thread-safe provided that `disposeObject` and
72/// `disposeRep` are not called explicitly, meaning that all non-creator
73/// operations other than `disposeObject` and `disposeRep` on a given instance
74/// can be safely invoked simultaneously from multiple threads (`disposeObject`
75/// and `disposeRep` are meant to be implemented by types inheriting
76/// `bslma::SharedPtrRep`, and invoked only by `releaseRef` and
77/// `releaseWeakRef`). Note that there is no thread safety guarantees for
78/// operations on the managed object.
79///
80/// ## disposeObject and disposeRep {#bslma_sharedptrrep-disposeobject-and-disposerep}
81///
82///
83/// `disposeObject` is meant to act as the destructor of the managed object and
84/// each derived class must override this method to perform an action that
85/// releases the shared object from management, such as deleting the managed
86/// object. `disposeObject` will be called when the last shared reference to
87/// the object has been released using `releaseRef`.
88///
89/// `disposeRep` is meant to act as the destructor of `bslma::SharedPtrRep`.
90/// The destructor of `bslma::SharedPtrRep` is declared as private and cannot be
91/// called. The derived class must override `disposeRep` to perform an action
92/// such as deallocating the memory of the instance of the derived class.
93/// `disposeRep` will be called when both the last shared reference and the last
94/// weak reference to the object has been released using `releaseRef` or
95/// `releaseWeakRef`.
96///
97/// ## Usage {#bslma_sharedptrrep-usage}
98///
99///
100/// The following example demonstrates how to implement a shared
101/// `bdlt::Datetime` using `bslma::SharedPtrRep`. In this example, the
102/// implementation will store an object of `bdlt::Datetime` in-place. First, we
103/// define an implementation of `bslma::SharedPtrRep`:
104/// @code
105/// class MySharedDatetimeRepImpl : public bslma::SharedPtrRep {
106/// // Implementation of 'bslma::SharedPtrRep' for an in-place
107/// // 'bdlt::Datetime' object.
108///
109/// // DATA
110/// bslma::Allocator *d_allocator_p; // memory allocator (held, not owned)
111/// bdlt::Datetime d_instance; // in-place object
112///
113/// private:
114/// // NOT IMPLEMENTED
115/// MySharedDatetimeRepImpl(const MySharedDatetimeRepImpl&);
116/// MySharedDatetimeRepImpl& operator=(const MySharedDatetimeRepImpl&);
117///
118/// public:
119/// // CREATORS
120/// MySharedDatetimeRepImpl(bslma::Allocator *basicAllocator,
121/// int year,
122/// int month,
123/// int day);
124/// // Create a shared representation of a 'bdlt::Datetime' object
125/// // having the specified 'year', 'month' and 'day' using the
126/// // specified 'basicAllocator' to supply memory.
127///
128/// // MANIPULATORS
129/// virtual void disposeRep();
130/// // Dispose of this 'MySharedDatetimeRepImpl' object.
131///
132/// virtual void disposeObject();
133/// // Dispose of the managed 'bdlt::Datetime' object.
134///
135/// // ACCESSORS
136/// bdlt::Datetime *ptr();
137/// // Return the address of the modifiable managed 'bdlt::Datetime'
138/// // object.
139///
140/// virtual void *originalPtr() const;
141/// // Return the address of the modifiable managed 'bdlt::Datetime'
142/// // object.
143/// };
144/// @endcode
145/// Next, we define the implementation:
146/// @code
147/// // CREATORS
148/// MySharedDatetimeRepImpl::MySharedDatetimeRepImpl(
149/// bslma::Allocator *basicAllocator,
150/// int year,
151/// int month,
152/// int day)
153/// : d_allocator_p(basicAllocator)
154/// , d_instance(year, month, day)
155/// {
156/// }
157///
158/// void MySharedDatetimeRepImpl::disposeRep()
159/// {
160/// d_allocator_p->deallocate(this);
161/// }
162///
163/// void MySharedDatetimeRepImpl::disposeObject()
164/// {
165/// d_instance.~bdlt::Datetime();
166/// }
167///
168/// bdlt::Datetime *MySharedDatetimeRepImpl::ptr()
169/// {
170/// return &d_instance;
171/// }
172///
173/// void *MySharedDatetimeRepImpl::originalPtr() const {
174/// return const_cast<void*>(static_cast<const void *>(&d_instance));
175/// }
176/// @endcode
177/// Next, we implement a shared `bdlt::Datetime` class.
178/// @code
179/// class MySharedDatetimePtr {
180/// // This class provides a reference counted managed pointer to support
181/// // shared ownership of a 'bdlt::Datetime' object.
182///
183/// bdlt::Datetime *d_ptr_p; // pointer to the managed object
184/// bslma::SharedPtrRep *d_rep_p; // pointer to the representation object
185///
186/// private:
187/// // NOT IMPLEMENTED
188/// MySharedDatetimePtr& operator=(const MySharedDatetimePtr&);
189///
190/// public:
191/// // CREATORS
192/// MySharedDatetimePtr();
193/// // Create an empty shared datetime.
194///
195/// MySharedDatetimePtr(bdlt::Datetime* ptr, bslma::SharedPtrRep* rep);
196/// // Create a shared datetime that adopts ownership of the specified
197/// // 'ptr' and the specified 'rep'.
198///
199/// MySharedDatetimePtr(const MySharedDatetimePtr& original);
200/// // Create a shared datetime that refers to the same object managed
201/// // by the specified 'original'
202///
203/// ~MySharedDatetimePtr();
204/// // Destroy this shared datetime and release the reference to the
205/// // 'bdlt::Datetime' object to which it might be referring. If this
206/// // is the last shared reference, deleted the managed object.
207///
208/// // MANIPULATORS
209/// void createInplace(bslma::Allocator *basicAllocator,
210/// int year,
211/// int month,
212/// int day);
213/// // Create a new 'MySharedDatetimeRepImpl', using the specified
214/// // 'basicAllocator' to supply memory, using the specified 'year',
215/// // 'month' and 'day' to initialize the 'bdlt::Datetime' within the
216/// // newly created 'MySharedDatetimeRepImpl', and make this
217/// // object refer to the newly created 'bdlt::Datetime' object.
218///
219/// // ACCESSORS
220/// bdlt::Datetime& operator*() const;
221/// // Return a reference to the modifiable 'bdlt::Datetime' to which
222/// // this object refers.
223///
224/// bdlt::Datetime *operator->() const;
225/// // Return the address of the modifiable 'bdlt::Datetime' to which
226/// // this object refers.
227///
228/// bdlt::Datetime *ptr() const;
229/// // Return the address of the modifiable 'bdlt::Datetime' to which
230/// // this object refers.
231/// };
232/// @endcode
233/// Finally, we implement `MySharedDatetimePtr`:
234/// @code
235/// MySharedDatetimePtr::MySharedDatetimePtr()
236/// : d_ptr_p(0)
237/// , d_rep_p(0)
238/// {
239/// }
240///
241/// MySharedDatetimePtr::MySharedDatetimePtr(bdlt::Datetime *ptr,
242/// bslma::SharedPtrRep *rep)
243/// : d_ptr_p(ptr)
244/// , d_rep_p(rep)
245/// {
246/// }
247///
248/// MySharedDatetimePtr::MySharedDatetimePtr(
249/// const MySharedDatetimePtr& original)
250/// : d_ptr_p(original.d_ptr_p)
251/// , d_rep_p(original.d_rep_p)
252/// {
253/// if (d_ptr_p) {
254/// d_rep_p->acquireRef();
255/// } else {
256/// d_rep_p = 0;
257/// }
258/// }
259///
260/// MySharedDatetimePtr::~MySharedDatetimePtr()
261/// {
262/// if (d_rep_p) {
263/// d_rep_p->releaseRef();
264/// }
265/// }
266///
267/// void MySharedDatetimePtr::createInplace(bslma::Allocator *basicAllocator,
268/// int year,
269/// int month,
270/// int day)
271/// {
272/// basicAllocator = bslma::Default::allocator(basicAllocator);
273/// MySharedDatetimeRepImpl *rep = new (*basicAllocator)
274/// MySharedDatetimeRepImpl(basicAllocator,
275/// year,
276/// month,
277/// day);
278/// MySharedDatetimePtr temp(rep->ptr(), rep);
279/// bsl::swap(d_ptr_p, temp.d_ptr_p);
280/// bsl::swap(d_rep_p, temp.d_rep_p);
281/// }
282///
283/// bdlt::Datetime& MySharedDatetimePtr::operator*() const
284/// {
285/// return *d_ptr_p;
286/// }
287///
288/// bdlt::Datetime *MySharedDatetimePtr::operator->() const
289/// {
290/// return d_ptr_p;
291/// }
292///
293/// bdlt::Datetime *MySharedDatetimePtr::ptr() const
294/// {
295/// return d_ptr_p;
296/// }
297/// @endcode
298/// @}
299/** @} */
300/** @} */
301
302/** @addtogroup bsl
303 * @{
304 */
305/** @addtogroup bslma
306 * @{
307 */
308/** @addtogroup bslma_sharedptrrep
309 * @{
310 */
311
312#include <bslscm_version.h>
313
314#include <bsls_assert.h>
315#include <bsls_atomic.h>
316
317#include <typeinfo>
318
319
320namespace bslma {
321
322 // ==================
323 // class SharedPtrRep
324 // ==================
325
326/// This class provides a partially implemented shared pointer
327/// representation ("letter") protocol. The class provides two counters for
328/// storing the number of shared and weak references, and functions to
329/// increment and decrement these counters. In addition, this class
330/// provides protocol methods that allow concrete implementations to specify
331/// what action should be taken when these counts reach zero. The function
332/// `disposeRep` is responsible for destroying this object, it is called
333/// when the reference count to this object reaches zero. Thus, the
334/// destructor of this object is declared as protected and should never be
335/// invoked.
336///
337/// See @ref bslma_sharedptrrep
339
340 // DATA
341 bsls::AtomicInt d_adjustedSharedCount;
342 // Counter storing a value that allows us to
343 // calculate the number of shared references.
344 // The numerical value of 'd_adjustedSharedCount'
345 // is: 2 * number of shared references, plus 1 if
346 // any weak references were *ever* created.
347
348 bsls::AtomicInt d_adjustedWeakCount;
349 // Counter storing a value that allows us to
350 // calculate the number of weak references. The
351 // numerical value of 'd_adjustedWeakCount' is:
352 // 2 * number of weak references, plus 1 if there
353 // are any *outstanding* shared references.
354
355 private:
356 // NOT IMPLEMENTED
357 SharedPtrRep(const SharedPtrRep&); // = delete
358 SharedPtrRep& operator=(const SharedPtrRep&); // = delete
359
360 // PRIVATE ACCESSORS
361
362 /// Do nothing. Note that this function is added to avoid including a
363 /// (redundant) vtable into every translation unit that includes this
364 /// type. Although we expect that these redundant vtables, identified
365 /// by the `-Wweak-vtables` warning of the clang compiler (version 4.0
366 /// and higher), will be consolidated by the linker, this workaround
367 /// avoids the space being used in the generated object files, which may
368 /// be important for very heavily used types like this one.
369 /// Implementing a virtual function out-of-line enables the compiler to
370 /// use this component translation unit as a "home" for the single
371 /// shared copy of the vtable.
372 virtual void vtableDummy() const;
373
374 protected:
375 // PROTECTED CREATORS
376
377 /// Destroy this representation object. Note that this destructor is
378 /// not intended to be invoked polymorphically, and is marked `virtual`
379 /// only to silence frequent warnings on popular compilers.
380 virtual ~SharedPtrRep();
381
382 public:
383 // CLASS METHODS
384
385 /// Release the shared reference to an object held by the `SharedPtrRep`
386 /// object that is pointed to be by specified `rep`. The behavior is
387 /// undefined unless `rep` points to an object whose complete type
388 /// publicly and unambiguously derives from `SharedPtrRep`. Note that
389 /// the first argument is ignored. Also note that this function serves
390 /// as the `ManagedPtr` deleter when converting a `bsl::shared_ptr` to a
391 /// `bslma::ManagedPtr`.
392 static void managedPtrDeleter(void *, void *rep);
393
394 /// This function has no effect. The behavior is undefined unless `rep`
395 /// is null. Note that this function serves as the managed ptr deleter
396 /// when converting an empty or null `bsl::shared_ptr` to a
397 /// `bslma::ManagedPtr`.
398 static void managedPtrEmptyDeleter(void *, void *rep);
399
400 // CREATORS
401
402 /// Create a `SharedPtrRep` object having one shared reference and no
403 /// weak references.
404 SharedPtrRep();
405
406 // PURE VIRTUAL FUNCTIONS
407
408 /// Dispose of the shared object referred to by this representation.
409 /// This method is automatically invoked by `releaseRef` when the number
410 /// of shared references reaches zero and should not be explicitly
411 /// invoked otherwise. Note that this virtual `disposeObject` method
412 /// effectively serves as the shared object's destructor. Also note
413 /// that derived classes must override this method to perform the
414 /// appropriate action such as deleting the shared object.
415 virtual void disposeObject() = 0;
416
417 /// Dispose of this representation object. This method is automatically
418 /// invoked by `releaseRef` and `releaseWeakRef` when the number of weak
419 /// references and the number of shared references both reach zero and
420 /// should not be explicitly invoked otherwise. The behavior is
421 /// undefined unless `disposeObject` has already been called for this
422 /// representation. Note that this virtual `disposeRep` method
423 /// effectively serves as the representation object's destructor. Also
424 /// note that derived classes must override this method to perform
425 /// appropriate action such as deleting this representation, or
426 /// returning it to an object pool.
427 virtual void disposeRep() = 0;
428
429 /// Return a pointer to the deleter stored by the derived representation
430 /// (if any) if the deleter has the same type as that described by the
431 /// specified `type`, and a null pointer otherwise. Note that while
432 /// this methods appears to be a simple accessor, it is declared as non-
433 /// `const` qualified to support representations storing the deleter
434 /// directly as a data member.
435 virtual void *getDeleter(const std::type_info& type) = 0;
436
437 /// Return the (untyped) address of the modifiable shared object
438 /// referred to by this representation.
439 virtual void *originalPtr() const = 0;
440
441 // MANIPULATORS
442
443 /// Atomically acquire a shared reference to the shared object referred
444 /// to by this representation. The behavior is undefined unless
445 /// `0 < numReferences()`.
446 void acquireRef();
447
448 /// Atomically acquire a weak reference to the shared object referred to
449 /// by this representation. The behavior is undefined unless
450 /// `0 < numWeakReferences() || 0 < numReferences()`.
452
453#ifndef BDE_OMIT_INTERNAL_DEPRECATED
454 /// Atomically increment the number of shared references to the shared
455 /// object referred to by this representation by the optionally
456 /// specified `incrementAmount`. The behavior is undefined unless
457 /// `0 < incrementAmount` and `0 < numReferences()`.
458 ///
459 /// DEPRECATED: Use `acquireRef` instead.
460 void incrementRefs(int incrementAmount = 1);
461#endif // BDE_OMIT_INTERNAL_DEPRECATED
462
463 /// Atomically release a shared reference to the shared object referred
464 /// to by this representation, disposing of the shared object if all the
465 /// shared references to that object are released, and disposing of this
466 /// representation if all (shared and weak) references to that object
467 /// are released. The behavior is undefined unless
468 /// `0 < numReferences()`.
470
471 /// Atomically release a weak reference to the shared object referred to
472 /// by this representation, disposing of this representation if all
473 /// (shared and weak) references to the shared object are released. The
474 /// behavior is undefined unless `0 < numWeakReferences()`.
475 void releaseWeakRef();
476
477 /// Reset the number of shared references and the number of weak
478 /// references stored by this representation to the specified
479 /// `numSharedReferences` and `numWeakReferences` respectively. This
480 /// function is *not* thread-safe and users must ensure that they
481 /// serialize access to the `SharedPtrRep` object when calling this
482 /// function. Note that this function updates the counts, but does not
483 /// dispose of the representation or the object irrespective of the
484 /// values of `numSharedReferences` and `numWeakReferences`.
485 void resetCountsRaw(int numSharedReferences, int numWeakReferences);
486
487 /// Atomically acquire a shared reference to the shared object referred
488 /// to by this representation, if the number of shared references is
489 /// greater than 0, and do nothing otherwise. Return `true` if the
490 /// acquire succeeds, and `false` otherwise. The behavior is undefined
491 /// unless `0 < numWeakReferences() || 0 < numReferences()`.
493
494 // ACCESSORS
495
496 /// Return `true` if there is only one shared reference and no weak
497 /// references to the object referred to by this representation, and
498 /// `false` otherwise.
499 bool hasUniqueOwner() const;
500
501 /// Return a "snapshot" of the current number of shared references to
502 /// the shared object referred to by this representation object.
503 int numReferences() const;
504
505 /// Return a "snapshot" of the current number of weak references to the
506 /// shared object referred to by this representation object.
507 int numWeakReferences() const;
508
509};
510
511// ============================================================================
512// INLINE DEFINITIONS
513// ============================================================================
514
515 // ------------------
516 // class SharedPtrRep
517 // ------------------
518
519// PROTECTED CREATORS
520inline
524
525// CLASS METHODS
526inline
527void SharedPtrRep::managedPtrDeleter(void *, void *rep)
528{
529 BSLS_ASSERT_SAFE(rep);
530
531 static_cast<SharedPtrRep *>(rep)->releaseRef();
532}
533
534inline
536{
537 BSLS_ASSERT_SAFE(!rep);
538 (void)rep; // Silence unused argument warning in non-SAFE builds.
539}
540
541// CREATORS
542inline
544: d_adjustedSharedCount(2) // minimum consistency: relaxed
545, d_adjustedWeakCount(1) // minimum consistency: relaxed
546{
547}
548
549// MANIPULATORS
550inline
552{
554
555 d_adjustedSharedCount.addRelaxed(2); // minimum consistency: relaxed
556}
557
558#ifndef BDE_OMIT_INTERNAL_DEPRECATED
559inline
560void SharedPtrRep::incrementRefs(int incrementAmount)
561{
562 BSLS_ASSERT_SAFE(0 < incrementAmount);
564
565 d_adjustedSharedCount.addRelaxed(incrementAmount * 2);
566 // minimum consistency: relaxed
567}
568#endif // BDE_OMIT_INTERNAL_DEPRECATED
569
570inline
572{
574
575 const int weakCount = d_adjustedWeakCount.add(-2);
576 // release consistency: acquire/release
577 if (0 == weakCount) {
578 disposeRep();
579 }
580}
581
582// ACCESSORS
583inline
585{
586 const int sharedCount = d_adjustedSharedCount;
587 // release consistency: acquire
588 return 2 == sharedCount
589 || (3 == sharedCount
590 && 1 == d_adjustedWeakCount); // release consistency: acquire
591}
592
593inline
595{
596 const int sharedCount = d_adjustedSharedCount.loadRelaxed();
597 // minimum consistency: relaxed
598 return sharedCount / 2;
599}
600
601inline
603{
604 const int weakCount = d_adjustedWeakCount.loadRelaxed();
605 // minimum consistency: relaxed
606 return weakCount / 2;
607}
608
609} // close package namespace
610
611
612#endif
613
614// ----------------------------------------------------------------------------
615// Copyright 2013 Bloomberg Finance L.P.
616//
617// Licensed under the Apache License, Version 2.0 (the "License");
618// you may not use this file except in compliance with the License.
619// You may obtain a copy of the License at
620//
621// http://www.apache.org/licenses/LICENSE-2.0
622//
623// Unless required by applicable law or agreed to in writing, software
624// distributed under the License is distributed on an "AS IS" BASIS,
625// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
626// See the License for the specific language governing permissions and
627// limitations under the License.
628// ----------------------------- END-OF-FILE ----------------------------------
629
630/** @} */
631/** @} */
632/** @} */
Definition bslma_sharedptrrep.h:338
virtual void * getDeleter(const std::type_info &type)=0
virtual void * originalPtr() const =0
void resetCountsRaw(int numSharedReferences, int numWeakReferences)
void releaseWeakRef()
Definition bslma_sharedptrrep.h:571
SharedPtrRep()
Definition bslma_sharedptrrep.h:543
int numWeakReferences() const
Definition bslma_sharedptrrep.h:602
bool hasUniqueOwner() const
Definition bslma_sharedptrrep.h:584
virtual ~SharedPtrRep()
Definition bslma_sharedptrrep.h:521
virtual void disposeObject()=0
static void managedPtrEmptyDeleter(void *, void *rep)
Definition bslma_sharedptrrep.h:535
void incrementRefs(int incrementAmount=1)
Definition bslma_sharedptrrep.h:560
virtual void disposeRep()=0
static void managedPtrDeleter(void *, void *rep)
Definition bslma_sharedptrrep.h:527
int numReferences() const
Definition bslma_sharedptrrep.h:594
void acquireRef()
Definition bslma_sharedptrrep.h:551
Definition bsls_atomic.h:743
int addRelaxed(int value)
Definition bsls_atomic.h:1648
int loadRelaxed() const
Definition bsls_atomic.h:1738
int add(int value)
Definition bsls_atomic.h:1636
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1762
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition balxml_encoderoptions.h:68