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:
-
- 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 {
bslma::Allocator *d_allocator_p;
bdlt::Datetime d_instance;
private:
MySharedDatetimeRepImpl(const MySharedDatetimeRepImpl&);
MySharedDatetimeRepImpl& operator=(const MySharedDatetimeRepImpl&);
public:
MySharedDatetimeRepImpl(bslma::Allocator *basicAllocator,
int year,
int month,
int day);
virtual void disposeRep();
virtual void disposeObject();
bdlt::Datetime *ptr();
virtual void *originalPtr() const;
};
Next, we define the implementation:
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. 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;
}