Quick Links:

bal | bbl | bdl | bsl

Namespaces

Component bslma_sharedptrrep
[Package bslma]

Provide an abstract class for a shared object manager. More...

Namespaces

namespace  bslma

Detailed Description

Outline
Purpose:
Provide an abstract class for a shared object manager.
Classes:
bslma::SharedPtrRep shared pointer representation abstract class
See also:
Component bslstl_sharedptr, bslma_sharedptrrep_inplace, bslma_sharedptrrep_outofplace
Description:
This component provides a partially implemented abstract class, bslma::SharedPtrRep, for managing the lifetime of a shared object. bslma::SharedPtrRep provides a count of both shared and weak references to a shared object (described in more detail in the next section). In addition, bslma::SharedPtrRep provides protocol methods that allows a concrete implementation to specify what action should be taken when these reference counts reach zero.
Shared and Weak References:
There are two types of references to shared objects:
1) A shared reference allows users to share the ownership of an object and control its lifetime. A shared object is destroyed only when the last shared reference to it is released. The function acquireRef should be called when a new shared reference is created and releaseRef should be called when a share reference is removed.
2) A weak reference provides users conditional access to an object without sharing its ownership (or affecting its lifetime). A shared object can be destroyed even if there are weak references to it. The function acquireWeakRef should be called when a new weak reference is created and releaseWeakRef should be called when a weak reference is removed.
Thread Safety:
bslma::SharedPtrRep 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 implemented by types inheriting bslma::SharedPtrRep, and invoked only by releaseRef and releaseWeakRef). Note that there is no thread safety guarantees for operations on the managed object.
disposeObject and disposeRep:
disposeObject is meant to act as the destructor of the managed object and each derived class must override this method to perform an action that releases the shared object from management, such as deleting the managed object. disposeObject will be called when the last shared reference to the object has been released using releaseRef.
disposeRep is meant to act as the destructor of bslma::SharedPtrRep. The destructor of bslma::SharedPtrRep is declared as private and cannot be called. The derived class must override disposeRep to perform an action such as deallocating the memory of the instance of the derived class. disposeRep will be called when both the last shared reference and the last weak reference to the object has been released using releaseRef or releaseWeakRef.
Usage:
The following example demonstrates how to implement a shared bdlt::Datetime using bslma::SharedPtrRep. In this example, the implementation will store an object of bdlt::Datetime in-place. First, we define an implementation of bslma::SharedPtrRep:
  class MySharedDatetimeRepImpl : public bslma::SharedPtrRep {
      // Implementation of 'bslma::SharedPtrRep' for an in-place
      // 'bdlt::Datetime' object.

      // DATA
      bslma::Allocator *d_allocator_p; // memory allocator (held, not owned)
      bdlt::Datetime    d_instance;    // in-place object

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

    public:
      // CREATORS
      MySharedDatetimeRepImpl(bslma::Allocator *basicAllocator,
                              int               year,
                              int               month,
                              int               day);
          // Create a shared representation of a 'bdlt::Datetime' object
          // having the specified 'year', 'month' and 'day' using the
          // specified 'basicAllocator' to supply memory.

      // MANIPULATORS
      virtual void disposeRep();
          // Dispose of this 'MySharedDatetimeRepImpl' object.

      virtual void disposeObject();
          // Dispose of the managed 'bdlt::Datetime' object.

      // ACCESSORS
      bdlt::Datetime *ptr();
          // Return the address of the modifiable managed 'bdlt::Datetime'
          // object.

      virtual void *originalPtr() const;
          // Return the address of the modifiable managed 'bdlt::Datetime'
          // object.
  };
Next, we define the implementation:
  // CREATORS
  MySharedDatetimeRepImpl::MySharedDatetimeRepImpl(
                                            bslma::Allocator *basicAllocator,
                                            int               year,
                                            int               month,
                                            int               day)
  : d_allocator_p(basicAllocator)
  , d_instance(year, month, day)
  {
  }

  void MySharedDatetimeRepImpl::disposeRep()
  {
      d_allocator_p->deallocate(this);
  }

  void MySharedDatetimeRepImpl::disposeObject()
  {
      d_instance.~bdlt::Datetime();
  }

  bdlt::Datetime *MySharedDatetimeRepImpl::ptr()
  {
      return &d_instance;
  }

  void *MySharedDatetimeRepImpl::originalPtr() const {
      return const_cast<void*>(static_cast<const void *>(&d_instance));
  }
Next, we implement a shared bdlt::Datetime class.
  class MySharedDatetimePtr {
      // This class provides a reference counted managed pointer to support
      // shared ownership of a 'bdlt::Datetime' object.

      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();
          // Create an empty shared datetime.

      MySharedDatetimePtr(bdlt::Datetime* ptr, bslma::SharedPtrRep* rep);
          // Create a shared datetime that adopts ownership of the specified
          // 'ptr' and the specified 'rep'.

      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
      void createInplace(bslma::Allocator *basicAllocator,
                         int               year,
                         int               month,
                         int               day);
          // Create a new 'MySharedDatetimeRepImpl', using the specified
          // 'basicAllocator' to supply memory, using the specified 'year',
          // 'month' and 'day' to initialize the 'bdlt::Datetime' within the
          // newly created 'MySharedDatetimeRepImpl', and make this
          // object refer to the newly created 'bdlt::Datetime' object.

      // ACCESSORS
      bdlt::Datetime& operator*() const;
          // Return a reference to the modifiable 'bdlt::Datetime' to which
          // this object refers.

      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 implement MySharedDatetimePtr:
  MySharedDatetimePtr::MySharedDatetimePtr()
  : d_ptr_p(0)
  , d_rep_p(0)
  {
  }

  MySharedDatetimePtr::MySharedDatetimePtr(bdlt::Datetime      *ptr,
                                           bslma::SharedPtrRep *rep)
  : d_ptr_p(ptr)
  , d_rep_p(rep)
  {
  }

  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();
      }
  }

  void MySharedDatetimePtr::createInplace(bslma::Allocator *basicAllocator,
                                          int               year,
                                          int               month,
                                          int               day)
  {
      basicAllocator = bslma::Default::allocator(basicAllocator);
      MySharedDatetimeRepImpl *rep = new (*basicAllocator)
                                      MySharedDatetimeRepImpl(basicAllocator,
                                                              year,
                                                              month,
                                                              day);
      MySharedDatetimePtr temp(rep->ptr(), rep);
      bsl::swap(d_ptr_p, temp.d_ptr_p);
      bsl::swap(d_rep_p, temp.d_rep_p);
  }

  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;
  }