Quick Links:

bal | bbl | bdl | bsl

Namespaces

Component bslma_sharedptroutofplacerep
[Package bslma]

Provide an out-of-place implementation of bslma::SharedPtrRep. More...

Namespaces

namespace  bslma

Detailed Description

Outline
Purpose:
Provide an out-of-place implementation of bslma::SharedPtrRep.
Classes:
bslma::SharedPtrOutofplaceRep out-of-place shared pointer implementation
See also:
bslma_sharedptr, Component bslma_sharedptrrep, Component bslma_sharedptrinplacerep
Description:
This component provides a concrete implementation of bslma::SharedPtrRep for managing objects of the parameterized TYPE that are stored outside of the representation. When all references to the out-of-place object are released using releaseRef, the deleter of the parameterized DELETER type is invoked to delete the shared object.
Thread Safety:
bslma::SharedPtrOutofplaceRep is thread-safe provided that disposeObject and disposeRep are not called explicitly, meaning that all non-creator operations other than disposeObject and disposeRep on a given instance can be safely invoked simultaneously from multiple threads (disposeObject and disposeRep are meant to be invoked only by releaseRef and releaseWeakRef). Note that there is no thread safety guarantees for operations on the managed object.
Deleters:
When the last shared reference to a shared object is released, the object is destroyed using the "deleter" provided when the associated shared pointer representation was created. bslma::SharedPtrOutofplaceRep supports two kinds of "deleter" objects, which vary in how they are invoked. A "function-like" deleter is any language entity that can be invoked such that the expression deleterInstance(objectPtr) is a valid expression, and a "factory" deleter is any language entity that can be invoked such that the expression deleterInstance.deleteObject(objectPtr) is a valid expression, where deleterInstance is an instance of the "deleter" object, and objectPtr is a pointer to the shared object. In summary:
  Deleter                     Expression used to destroy 'objectPtr'
  - - - - - - - -             - - - - - - - - - - - - - - - - - - -
  "function-like"             deleterInstance(objectPtr);
  "factory"                   deleterInstance.deleteObject(objectPtr);
The following are examples of function-like deleters that delete an object of MyType:
  void deleteObject(MyType *object);
      // Delete the specified 'object'.

  void releaseObject(MyType *object);
      // Release the specified 'object'.

  struct FunctionLikeDeleterObject {
      // This 'struct' provides an 'operator()' that can be used to delete a
      // 'MyType' object.

      void operator()(MyType *object);
          // Destroy the specified 'object'.
  };
The following on the other hand is an example of a factory deleter:
  class MyFactory {

     // . . .

     // MANIPULATORS
     MyType *createObject(bslma::Allocator *basicAllocator = 0);
         // Create a 'MyType' object.  Optionally specify a
         // 'basicAllocator' used to supply memory.  If 'basicAllocator' is
         // 0, the currently installed default allocator is used.

     void deleteObject(MyType *object);
         // Delete the specified 'object'.
  };
Note that deleteObject is provided by all bslma allocators and by any object that implements the bdlma::Deleter protocol. Thus, any of these objects can be used as a factory deleter. The purpose of this design is to allow bslma allocators and factories to be used seamlessly as deleters.
The selection of which expression is used by bslma::SharedPtrOutofplaceRep to destroy a shared object is based on how the deleter is passed to the shared pointer object: Deleters that are passed by address are assumed to be factory deleters, while those that are passed by value are assumed to be function-like. Note that if the wrong interface is used for a deleter, i.e., if a function-like deleter is passed by pointer, or a factory deleter is passed by value, and the expression used to delete the object is invalid, a compiler diagnostic will be emitted indicating the error.
Usage:
The following example demonstrates how to implement a shared bdlt::Datetime object using bslma::SharedPtrOutofplaceRep:
  class MySharedDatetimePtr {
      // This class provide a reference counted smart pointer to support
      // shared ownership of a 'bdlt::Datetime' object.

    private:
      bdlt::Datetime      *d_ptr_p;  // pointer to the managed object
      bslma::SharedPtrRep *d_rep_p;  // pointer to the representation object

    private:
      // NOT IMPLEMENTED
      MySharedDatetimePtr& operator=(const MySharedDatetimePtr&);

    public:
      // CREATORS
      MySharedDatetimePtr(bdlt::Datetime   *ptr,
                          bslma::Allocator *basicAllocator = 0);
          // Create a 'MySharedDatetimePtr' object to managed the specified
          // 'ptr'.  Optionally specify an 'basicAllocator' to allocate and
          // deallocate the internal representation and to destroy 'ptr' when
          // all references have been released.  The behavior is undefined
          // unless 'ptr' was allocated using memory supplied by
          // 'basicAllocator'.

      MySharedDatetimePtr(const MySharedDatetimePtr& original);
          // Create a shared datetime that refers to the same object managed
          // by the specified 'original'

      ~MySharedDatetimePtr();
          // Destroy this shared datetime and release the reference to the
          // 'bdlt::Datetime' object to which it might be referring.  If this
          // is the last shared reference, deleted the managed object.

      // MANIPULATORS
      bdlt::Datetime& operator*() const;
          // Return a reference offering modifiable access to the shared
          // datetime.

      bdlt::Datetime *operator->() const;
          // Return the address of the modifiable 'bdlt::Datetime' to which
          // this object refers.

      bdlt::Datetime *ptr() const;
          // Return the address of the modifiable 'bdlt::Datetime' to which
          // this object refers.
  };
Finally, we define the implementation.
  MySharedDatetimePtr::MySharedDatetimePtr(bdlt::Datetime   *ptr,
                                           bslma::Allocator *basicAllocator)
  {
      d_ptr_p = ptr;
      d_rep_p =
          bslma::SharedPtrOutofplaceRep<bdlt::Datetime, bslma::Allocator *>::
                      makeOutofplaceRep(ptr, basicAllocator, basicAllocator);
  }

  MySharedDatetimePtr::MySharedDatetimePtr(
                                         const MySharedDatetimePtr& original)
  : d_ptr_p(original.d_ptr_p)
  , d_rep_p(original.d_rep_p)
  {
      if (d_ptr_p) {
          d_rep_p->acquireRef();
      } else {
          d_rep_p = 0;
      }
  }

  MySharedDatetimePtr::~MySharedDatetimePtr()
  {
      if (d_rep_p) {
          d_rep_p->releaseRef();
      }
  }

  bdlt::Datetime& MySharedDatetimePtr::operator*() const {
      return *d_ptr_p;
  }

  bdlt::Datetime *MySharedDatetimePtr::operator->() const {
      return d_ptr_p;
  }

  bdlt::Datetime *MySharedDatetimePtr::ptr() const {
      return d_ptr_p;
  }