BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslma_sharedptrrep

Detailed Description

Outline

Purpose

Provide an abstract class for a shared object manager.

Classes

See also
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
// Return the address of the modifiable managed 'bdlt::Datetime'
// object.
virtual void *originalPtr() const;
// Return the address of the modifiable managed 'bdlt::Datetime'
// object.
};
Definition bdlt_datetime.h:331
Definition bslma_allocator.h:457
Definition bslma_sharedptrrep.h:338

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,
: 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;
}
void swap(array< VALUE_TYPE, SIZE > &lhs, array< VALUE_TYPE, SIZE > &rhs)
static Allocator * allocator(Allocator *basicAllocator=0)
Definition bslma_default.h:897