Simbody  3.7
SimTK::PIMPLHandle< HANDLE, IMPL, PTR > Class Template Reference

This class provides some infrastructure useful in making SimTK Private Implementation (PIMPL) classes. More...

Public Types

typedef PIMPLHandle< HANDLE, IMPL, PTR > HandleBase
 
typedef HandleBase ParentHandle
 

Public Member Functions

bool isEmptyHandle () const
 Returns true if this handle is empty, that is, does not refer to any implementation object. More...
 
bool isOwnerHandle () const
 Returns true if this handle is the owner of the implementation object to which it refers. More...
 
bool isSameHandle (const HANDLE &other) const
 Determine whether the supplied handle is the same object as "this" PIMPLHandle. More...
 
void disown (HANDLE &newOwner)
 Give up ownership of the implementation to an empty handle. More...
 
PIMPLHandlereferenceAssign (const HANDLE &source)
 "Copy" assignment but with shallow (pointer) semantics. More...
 
PIMPLHandlecopyAssign (const HANDLE &source)
 This is real copy assignment, with ordinary C++ object ("value") semantics. More...
 
void clearHandle ()
 Make this an empty handle, deleting the implementation object if this handle is the owner of it. More...
 
const IMPL & getImpl () const
 Get a const reference to the implementation associated with this Handle. More...
 
IMPL & updImpl ()
 Get a writable reference to the implementation associated with this Handle. More...
 
int getImplHandleCount () const
 Return the number of handles the implementation believes are referencing it. More...
 

Protected Member Functions

 PIMPLHandle ()
 The default constructor makes this an empty handle. More...
 
 PIMPLHandle (IMPL *p)
 This provides consruction of a handle referencing an existing implementation object. More...
 
 ~PIMPLHandle ()
 Note that the destructor is non-virtual. More...
 
 PIMPLHandle (const PIMPLHandle &source)
 The copy constructor makes either a deep (value) or shallow (reference) copy of the supplied source PIMPL object, based on whether this is a "pointer semantics" (PTR=true) or "object (value) semantics" (PTR=false, default) class. More...
 
PIMPLHandleoperator= (const PIMPLHandle &source)
 Copy assignment makes the current handle either a deep (value) or shallow (reference) copy of the supplied source PIMPL object, based on whether this is a "pointer sematics" (PTR=true) or "object (value) semantics" (PTR=false, default) class. More...
 
void setImpl (IMPL *p)
 Set the implementation for this empty handle. More...
 
bool hasSameImplementation (const HANDLE &other) const
 Determine whether the supplied handle is a reference to the same implementation object as is referenced by "this" PIMPLHandle. More...
 

Detailed Description

template<class HANDLE, class IMPL, bool PTR = false>
class SimTK::PIMPLHandle< HANDLE, IMPL, PTR >

This class provides some infrastructure useful in making SimTK Private Implementation (PIMPL) classes.

These consist of a "handle" class and an "implementation" class. The handle contains only a single pointer, which points to the implementation class whose definition is unknown to the SimTK client. The implementation class has a pointer back to one of the handles that points to it – that one is called the "owner handle" and is the only one which will delete the implementation object when the handle is deleted or goes out of scope. All other handles are merely references to the implementation object, and must not be used after the owner handle is deleted.

The methods defined below require a definition for the implementation class, so can't be instantiated on the client side. Instead they are instantiated on the library side when needed in the implementation of the PIMPL handle class derived from the PIMPLHandle base.

By the time of instantiation, we must have a definition for the IMPL class supplied to the templatized base class. We expect that the IMPL class will be derived from PIMPLImplementation declared below. We also expect to find certain methods defined, with these names and meanings:

IMPL* IMPL::clone() const
   This creates an implementation object identical to the one
   we have, except that its owner handle is set to null. We 
   expect the owner handle to be filled in by the derived 
   Handle class, which should have initiated the PIMPLHandle
   operation which had the need to clone().

const HANDLE& IMPL::getOwnerHandle() const
   If the IMPL object does not have an owner, this is expected
   to assert(); that would indicate that the derived Handle class
   did not properly register itself as the owner upon construction.
   Otherwise, this routine returns a reference to the *derived*
   Handle class, NOT to the PIMPLHandle parent class! We expect,
   however that the Handle class was derived from this PIMPLHandle
   so that we can static_cast up here and then compare with 'this'.

Usage: class MySecretImpl; class MyHandle : public PIMPLHandle<MyHandle,MySecretImpl>

There is an optional third template argument, a bool, which can be set true if you want the handle to have pointer semantics rather than the usual object ("value") semantics. Pointer semantics objects have shallow copy constuctor and copy assignment implementations so that they are normally references to objects rather than owners, and pointer semantics owner handles can't be the target of an assignment.

Member Typedef Documentation

◆ HandleBase

template<class HANDLE, class IMPL, bool PTR = false>
typedef PIMPLHandle<HANDLE, IMPL, PTR> SimTK::PIMPLHandle< HANDLE, IMPL, PTR >::HandleBase

◆ ParentHandle

template<class HANDLE, class IMPL, bool PTR = false>
typedef HandleBase SimTK::PIMPLHandle< HANDLE, IMPL, PTR >::ParentHandle

Constructor & Destructor Documentation

◆ PIMPLHandle() [1/3]

template<class HANDLE, class IMPL, bool PTR = false>
SimTK::PIMPLHandle< HANDLE, IMPL, PTR >::PIMPLHandle ( )
inlineprotected

The default constructor makes this an empty handle.

◆ PIMPLHandle() [2/3]

template<class HANDLE , class IMPL, bool PTR>
SimTK::PIMPLHandle< HANDLE, IMPL, PTR >::PIMPLHandle ( IMPL *  p)
explicitprotected

This provides consruction of a handle referencing an existing implementation object.

If the supplied pointer is null the result is the same as the default constructor.

◆ ~PIMPLHandle()

template<class HANDLE , class IMPL , bool PTR>
SimTK::PIMPLHandle< HANDLE, IMPL, PTR >::~PIMPLHandle ( )
protected

Note that the destructor is non-virtual.

This is a concrete class and so should be all the handle classes derived from it. If this handle is the owner of its implementation, the destructor will destroy the implementation object as well. Any other handles referencing the same implementation will then be invalid, although there will be automated detection of that. Be very careful to ensure that owner handles always outlive their reference handles.

◆ PIMPLHandle() [3/3]

template<class HANDLE , class IMPL, bool PTR>
SimTK::PIMPLHandle< HANDLE, IMPL, PTR >::PIMPLHandle ( const PIMPLHandle< HANDLE, IMPL, PTR > &  source)
protected

The copy constructor makes either a deep (value) or shallow (reference) copy of the supplied source PIMPL object, based on whether this is a "pointer semantics" (PTR=true) or "object (value) semantics" (PTR=false, default) class.

See also
referenceAssign
copyAssign

Member Function Documentation

◆ isEmptyHandle()

template<class HANDLE, class IMPL, bool PTR = false>
bool SimTK::PIMPLHandle< HANDLE, IMPL, PTR >::isEmptyHandle ( ) const
inline

Returns true if this handle is empty, that is, does not refer to any implementation object.

◆ isOwnerHandle()

template<class HANDLE , class IMPL , bool PTR>
bool SimTK::PIMPLHandle< HANDLE, IMPL, PTR >::isOwnerHandle ( ) const

Returns true if this handle is the owner of the implementation object to which it refers.

An empty handle is not considered by this method to be an owner. You can check for an empty handle using isEmptyHandle().

See also
isEmptyHandle()

◆ isSameHandle()

template<class HANDLE, class IMPL , bool PTR>
bool SimTK::PIMPLHandle< HANDLE, IMPL, PTR >::isSameHandle ( const HANDLE &  other) const

Determine whether the supplied handle is the same object as "this" PIMPLHandle.

◆ disown()

template<class HANDLE, class IMPL , bool PTR>
void SimTK::PIMPLHandle< HANDLE, IMPL, PTR >::disown ( HANDLE &  newOwner)

Give up ownership of the implementation to an empty handle.

The current handle retains a reference to the implementation but is no longer its owner. This method requires the current handle to be an owner, and the supplied handle to be empty.

◆ referenceAssign()

template<class HANDLE, class IMPL , bool PTR>
PIMPLHandle< HANDLE, IMPL, PTR > & SimTK::PIMPLHandle< HANDLE, IMPL, PTR >::referenceAssign ( const HANDLE &  source)

"Copy" assignment but with shallow (pointer) semantics.

As long as this is not an owner handle already, make it reference the source implementation. It is not allowed for an owner handle to be the target of a reference assignment; clear the handle explicitly first with clearHandle() if you want to do that. This is the default copy and assignment behavior for pointer semantics handle classes (that is, those which set the PTR template argument to true). Caution: although the PIMPLHandle is taken const here, we obtain a writable pointer to the implementation, meaning that it can be modified through the reference handle if that handle is non-const.

See also
copyAssign()
operator=()
clearHandle()

◆ copyAssign()

template<class HANDLE, class IMPL , bool PTR>
PIMPLHandle< HANDLE, IMPL, PTR > & SimTK::PIMPLHandle< HANDLE, IMPL, PTR >::copyAssign ( const HANDLE &  source)

This is real copy assignment, with ordinary C++ object ("value") semantics.

Deletes the current implementation if owned; then replaces with a new copy of the source implementation, of which this handle will be the owner. This is the default copy and assignment behavior for normal handle objects, that is, those that let the PTR template argument default or set it to false explicitly. Use referenceAssign() to make a handle refer to an existing implementation rather than creating a new copy.

See also
referenceAssign()

◆ clearHandle()

template<class HANDLE , class IMPL , bool PTR>
void SimTK::PIMPLHandle< HANDLE, IMPL, PTR >::clearHandle ( )

Make this an empty handle, deleting the implementation object if this handle is the owner of it.

A call to isEmptyHandle() will return true after this.

See also
isEmptyHandle()

◆ getImpl()

template<class HANDLE, class IMPL, bool PTR = false>
const IMPL& SimTK::PIMPLHandle< HANDLE, IMPL, PTR >::getImpl ( ) const
inline

Get a const reference to the implementation associated with this Handle.

This will throw an exception if there is no implementation.

◆ updImpl()

template<class HANDLE, class IMPL, bool PTR = false>
IMPL& SimTK::PIMPLHandle< HANDLE, IMPL, PTR >::updImpl ( )
inline

Get a writable reference to the implementation associated with this Handle.

Note that this requires writable access to the handle also. This will throw an exception if there is no implementation.

◆ getImplHandleCount()

template<class HANDLE , class IMPL , bool PTR>
int SimTK::PIMPLHandle< HANDLE, IMPL, PTR >::getImplHandleCount ( ) const

Return the number of handles the implementation believes are referencing it.

Throws an exception if there is no implementation. This is for degugging and consistency checking and shouldn't normally be used.

◆ operator=()

template<class HANDLE , class IMPL , bool PTR>
PIMPLHandle< HANDLE, IMPL, PTR > & SimTK::PIMPLHandle< HANDLE, IMPL, PTR >::operator= ( const PIMPLHandle< HANDLE, IMPL, PTR > &  source)
protected

Copy assignment makes the current handle either a deep (value) or shallow (reference) copy of the supplied source PIMPL object, based on whether this is a "pointer sematics" (PTR=true) or "object (value) semantics" (PTR=false, default) class.

In the case of a pointer semantics class, an owner handle can not be the target of an assignment. You can call copyAssign() directly if you want to make a fresh copy of the source, or you can clear this handle first with clearHandle() and then use operator=() or referenceAssign() to turn this handle into a mere reference to the source.

See also
referenceAssign
copyAssign

◆ setImpl()

template<class HANDLE , class IMPL, bool PTR>
void SimTK::PIMPLHandle< HANDLE, IMPL, PTR >::setImpl ( IMPL *  p)
protected

Set the implementation for this empty handle.

This may result in either an owner or reference handle, depending on the owner handle reference stored in the implementation object. This will throw an exception if the handle is already occupied; it cannot be used to replace one implementation with another.

◆ hasSameImplementation()

template<class HANDLE, class IMPL , bool PTR>
bool SimTK::PIMPLHandle< HANDLE, IMPL, PTR >::hasSameImplementation ( const HANDLE &  other) const
protected

Determine whether the supplied handle is a reference to the same implementation object as is referenced by "this" PIMPLHandle.


The documentation for this class was generated from the following files: