PIMPLHandle< HANDLE, IMPL, PTR > Class Template Reference

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

#include <PrivateImplementation.h>

List of all members.

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

Protected Member Functions

 PIMPLHandle (IMPL *p=0)
 This serves as the default constructor, which will construct the handle with an empty implementation, and as a way to construct a handle referencing an existing implementation object.
 ~PIMPLHandle ()
 Note that the destructor is non-virtual.
 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 sematics" (PTR=true) or "object (value) semantics" (PTR=false, default) class.
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.
void setImpl (IMPL *p)
 Set the implementation for this empty handle.
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.

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

typedef PIMPLHandle<HANDLE, IMPL, PTR> HandleBase

Constructor & Destructor Documentation

PIMPLHandle ( IMPL *  p = 0  )  [inline, explicit, protected]

This serves as the default constructor, which will construct the handle with an empty implementation, and as a way to construct a handle referencing an existing implementation object.

~PIMPLHandle (  )  [inline, 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.

References PIMPLHandle< HANDLE, IMPL, PTR >::clearHandle().

PIMPLHandle ( const PIMPLHandle< HANDLE, IMPL, PTR > &  source  )  [inline, 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 sematics" (PTR=true) or "object (value) semantics" (PTR=false, default) class.

See also:
referenceAssign
copyAssign

References PIMPLHandle< HANDLE, IMPL, PTR >::copyAssign(), and PIMPLHandle< HANDLE, IMPL, PTR >::referenceAssign().


Member Function Documentation

void clearHandle (  )  [inline]

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

References PIMPLHandle< HANDLE, IMPL, PTR >::isEmptyHandle(), and PIMPLHandle< HANDLE, IMPL, PTR >::isOwnerHandle().

Referenced by PIMPLHandle< HANDLE, IMPL, PTR >::copyAssign(), PIMPLHandle< HANDLE, IMPL, PTR >::referenceAssign(), and PIMPLHandle< HANDLE, IMPL, PTR >::~PIMPLHandle().

PIMPLHandle< HANDLE, IMPL, PTR > & copyAssign ( const HANDLE &  source  )  [inline]

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

References PIMPLHandle< HANDLE, IMPL, PTR >::clearHandle(), and PIMPLHandle< HANDLE, IMPL, PTR >::isSameHandle().

Referenced by PIMPLHandle< HANDLE, IMPL, PTR >::operator=(), and PIMPLHandle< HANDLE, IMPL, PTR >::PIMPLHandle().

void disown ( HANDLE &  newOwner  )  [inline]

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.

References PIMPLHandle< HANDLE, IMPL, PTR >::isEmptyHandle(), and PIMPLHandle< HANDLE, IMPL, PTR >::isSameHandle().

Referenced by CompoundSystem::adoptCompound().

const IMPL& getImpl (  )  const [inline]

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

This will throw an exception if there is no implementation.

int getImplHandleCount (  )  const [inline]

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.

References PIMPLHandle< HANDLE, IMPL, PTR >::isEmptyHandle().

bool hasSameImplementation ( const HANDLE &  other  )  const [inline, protected]

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

Referenced by PIMPLHandle< HANDLE, IMPL, PTR >::referenceAssign().

bool isEmptyHandle (  )  const [inline]
bool isOwnerHandle (  )  const [inline]

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

Referenced by PIMPLHandle< HANDLE, IMPL, PTR >::clearHandle(), and PIMPLHandle< HANDLE, IMPL, PTR >::referenceAssign().

bool isSameHandle ( const HANDLE &  other  )  const [inline]

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

Referenced by PIMPLHandle< HANDLE, IMPL, PTR >::copyAssign(), and PIMPLHandle< HANDLE, IMPL, PTR >::disown().

PIMPLHandle< HANDLE, IMPL, PTR > & operator= ( const PIMPLHandle< HANDLE, IMPL, PTR > &  source  )  [inline, 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

References PIMPLHandle< HANDLE, IMPL, PTR >::copyAssign(), and PIMPLHandle< HANDLE, IMPL, PTR >::referenceAssign().

PIMPLHandle< HANDLE, IMPL, PTR > & referenceAssign ( const HANDLE &  source  )  [inline]

"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()

References PIMPLHandle< HANDLE, IMPL, PTR >::clearHandle(), PIMPLHandle< HANDLE, IMPL, PTR >::hasSameImplementation(), and PIMPLHandle< HANDLE, IMPL, PTR >::isOwnerHandle().

Referenced by PIMPLHandle< HANDLE, IMPL, PTR >::operator=(), and PIMPLHandle< HANDLE, IMPL, PTR >::PIMPLHandle().

void setImpl ( IMPL *  p  )  [inline, 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.

References PIMPLHandle< HANDLE, IMPL, PTR >::isEmptyHandle().

IMPL& 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.


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

Generated on Wed Dec 30 11:05:27 2009 for SimTKcore by  doxygen 1.6.1