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

Macros

#define bslma_DestructorProctor   bslma::DestructorProctor
 This alias is defined for backward compatibility.
 

Detailed Description

Outline

Purpose

Provide a proctor to conditionally manage an object.

Classes

See also
bslma_destructorguard, bslma_autodestructor

Description

This component provides a proctor class template, bslma::DestructorProctor, to conditionally manage an (otherwise-unmanaged) object of parameterized TYPE supplied at construction. If not explicitly released, the managed object is destroyed automatically when the proctor object goes out of scope by calling the object's destructor. Note that after a proctor object releases its managed object, the same proctor can be reused to conditionally manage another object by invoking the reset method.

Usage

The bslma::DestructorProctor is normally used to manage objects that are constructed sequentially in a block of memory provided. This is often the case when memory management and primitive helpers are implemented in different components. An example would be the construction of a pair object within another container with the help of a scalar primitive helper (see bslma_constructionutil ). After the first object is constructed in the provided memory, it should be protected in case the constructor of the second object throws. The following example illustrates a typical use of the bslma::DestructorProctor.

First, suppose we have a pair class similar to std::pair:

// MyPair.h
// ...
/// This class provides a pair container to pair two different objects,
/// one of parameterized `TYPE1`, and the other of parameterized
/// `TYPE2`.
template <class TYPE1, class TYPE2>
class MyPair {
public:
// PUBLIC TYPES
typedef TYPE1 firstType;
typedef TYPE2 secondType;
// PUBLIC DATA
TYPE1 first; // first object
TYPE2 second; // second object
// Declare trait `my_PairTrait`.
// ...
public:
// CREATORS
// ...
/// Create a `MyPair` object that holds a copy of the specified
/// `iFirst` and `iSecond`. Optionally specify `basicAllocator` to
/// supply memory. If `basicAllocator` is zero, the global default
/// allocator will be used to supply memory.
MyPair(const TYPE1& iFirst,
const TYPE2& iSecond,
bslma::Allocator *basic_Allocator = 0)
: first(iFirst)
, second(iSecond)
, d_allocator_p(bslma::Default::allocator(basic_Allocator))
{
}
// ...
};
Definition bslma_allocator.h:457
Definition balxml_encoderoptions.h:68

Note that parts of the implementation, including the my_PairTrait declaration, are elided. The my_PairTrait will be used by the primitive helper to customize implementations for objects that are pairs.

We now implement the primitive helper:

// MyPrimitives.h
// ...
/// This `struct` provides a namespace for primitive functions used to
/// construct, destroy, insert, append and remove objects.
struct MyPrimitives {
private:
// PRIVATE TYPES
enum { PAIR_TRAIT = 1, NIL_TRAIT = 0 };
public:
// CLASS METHODS
/// Copy construct the specified `original` into the specified
/// `address` using the specified `basicAllocator` (if the
/// copy constructor of `TYPE` takes an allocator).
template <class TYPE>
static void copyConstruct(TYPE *address,
const TYPE& original,
bslma::Allocator *basicAllocator);
/// Copy construct the specified `original` into the specified
/// `address` using the specified `basicAllocator` (if the
/// copy constructor of `TYPE` takes an allocator). Note that
/// the last parameter is used only for overload resolution.
template <class TYPE>
static void copyConstruct(TYPE *address,
const TYPE& original,
bslma::Allocator *basicAllocator,
/// Copy construct the specified `original` into the specified
/// `address` using the specified `basicAllocator` (if the
/// copy constructor of `TYPE` takes an allocator). Note that
/// the last parameter is used only for overload resolution.
template <class TYPE>
static void copyConstruct(TYPE *address,
const TYPE& original,
bslma::Allocator *basicAllocator,
};
template <class TYPE>
inline
void MyPrimitives::copyConstruct(TYPE *address,
const TYPE& original,
bslma::Allocator *basicAllocator)
{
copyConstruct(address,
original,
basicAllocator,
(typename my_HasPairTrait<TYPE>::type *)0);
}
Definition bslmf_integralconstant.h:244

The implementation of copyConstruct constructs the pair object in two steps because of the use of allocators. We cannot simply pass the allocator to the copy constructor of the pair object (since std::pair does not take an allocator). Therefore, we copy construct first and second directly in the pair object.

template <class TYPE>
inline
void MyPrimitives::copyConstruct(TYPE *address,
const TYPE& original,
bslma::Allocator *basicAllocator,
{
copyConstruct(&address->first, original.first, basicAllocator);
//**************************************************
// Note the use of the destructor proctor (below). *
//**************************************************
&address->first);
copyConstruct(&address->second, original.second, basicAllocator);
//********************************************************
// Note that the destructor proctor is released (below). *
//********************************************************
proctor.release();
}
template <class TYPE>
inline
void MyPrimitives::copyConstruct(TYPE *address,
const TYPE& original,
bslma::Allocator *basicAllocator,
{
new(address)TYPE(original, basicAllocator);
}
Definition bslma_destructorproctor.h:259

Note that the implementation of my_HasPairTrait is not shown. It is used to detect whether TYPE has my_PairTrait or not (see bslalg_typetraits , bslalg_typetraitpair ).

In the above implementation, if the copy construction of the second object in the pair throws, all memory (and any other resources) acquired as a result of copying the (not-yet-managed) object would be leaked. Using the bslma::DestructorProctor prevents the leaks by invoking the destructor of the proctored object automatically should the proctor go out of scope before the release method of the proctor is called (such as when the function exits prematurely due to an exception).

Note that the copyConstruct method assumes the copy constructor of TYPE::firstType and TYPE::secondType takes an allocator as a second argument. In production code, a constructor proxy that checks the traits of TYPE::firstType and TYPE::secondType (to determine whether they uses bslma::Allocator) should be used (see bslalg_constructorproxy ).

Macro Definition Documentation

◆ bslma_DestructorProctor

#define bslma_DestructorProctor   bslma::DestructorProctor