// RsrcCtrlr.h -- ReSouRCe ConTRoLleR template class // (c) Copyright Schlumberger Technology Corp., unpublished work, created // 1999. This computer program includes Confidential, Proprietary // Information and is a Trade Secret of Schlumberger Technology Corp. All // use, disclosure, and/or reproduction is prohibited unless authorized // in writing. All Rights Reserved. #if !defined(SLBCSP_RSRCCTRLR_H) #define SLBCSP_RSRCCTRLR_H // ResourceController is an abstract base template class to control // the acquisition and release of a resource. The controlled resource // (m_Resource) is a protected member. The class implements a handle // interface to safely access and manipulate that resource in // conjunction with the derived class. // // Example usages of the ResourceController are implementing the // "resource acquisition is initialization," locking and unlocking an // object for thread safety, and counted pointer idioms. // // // DERIVED CLASS RESPONSIBILITY: To complete the implementation, the // derived class must define the Acquire and Release methods to // perform the resource acquisition and release operations, // respectively. The ResourceController does not call Acquire in the // constructor since that method is defined by the derived class and // the derived portion of the object is not be considered constructed // at the time the base class constructor is called. For reasons of // symetry, ResourceController does not call Release in the // destructor. Therefore, it is the derived classes responsibility to // define constructors, a destructor, and call Acquire and Release in // those methods as appropriate. // // As with any derived class implementation, any assignment operators // defined by the derived class should call the the comparable // versions in ResourceController. // // CONSTRAINTS: T must support a default value (have a default // constructor). // // ResourceController was not designed to be referenced directly, that // is why all of it's methods (except Acquire and Release) are not // defined virtual. // // NOTE: Comparison helpers are defined at the end. template class ResourceController { public: // Types // PrivateDummy is a helper class to support validity testing of // ResourceController. This class together with the conversion // operator PrivateDummy const *() below allows // ResourceControllers to be tested for nullness (validity tests). // The implemenation allows these tests in a syntactically natural // way without allowing heterogeneous comparisons and that won't // violate the protections that ResourceController provides. The // technique is a variation from an article by Don Box in "Com // Smart Pointers Also Considered Harmful," 1996, C++ Report. class PrivateDummy {}; // C'tors/D'tors virtual ~ResourceController() throw () = 0; // Operators operator T() const; ResourceController & operator=(T const &rhs); ResourceController & operator=(ResourceController const &rhs); operator PrivateDummy const *() /* const */; // Enable validity test of ResourceController. See description of // PrivateDummy type. // making this a const routine causes compilation // problems in VC++ 6.0 for some reason. // Operations // Access T operator->() const; T operator*() const; // Predicates protected: // Types // C'tors/D'tors explicit ResourceController(T const &rResource = T()); ResourceController(ResourceController const &rhs); // Operators // Operations void DoAcquire(); virtual void DoAfterAssignment(); virtual void DoBeforeAssignment(); void DoRelease(); // Access // Predicates // Variables T m_Resource; private: // Types // C'tors/D'tors // Operators // Operations // Access // Predicates // Variables }; ///////////////////////// TEMPLATE METHODS ////////////////////////////// /////////////////////////// PUBLIC ///////////////////////////////// // Types // C'tors/D'tors template ResourceController::~ResourceController() throw() {} // Operators template ResourceController::operator T() const { return m_Resource; } template T ResourceController::operator->() const { return m_Resource; } template T ResourceController::operator*() const { return m_Resource; } template ResourceController::operator ResourceController::PrivateDummy const *() /* const */ { return m_Resource ? reinterpret_cast(this) : 0; } template ResourceController & ResourceController::operator=(T const &rhs) { if (m_Resource != rhs) { DoBeforeAssignment(); m_Resource = rhs; DoAfterAssignment(); } return *this; } template ResourceController & ResourceController::operator=(ResourceController const &rhs) { if (this != &rhs) { DoBeforeAssignment(); m_Resource = rhs.m_Resource; DoAfterAssignment(); } return *this; } // Operations // Access // Predicates // Static Variables /////////////////////////// PROTECTED ///////////////////////////////// // C'tors/D'tors template ResourceController::ResourceController(T const &rResource) : m_Resource(rResource) {} template ResourceController::ResourceController(ResourceController const &rhs) : m_Resource(rhs.m_Resource) {} // Operators // Operations template void ResourceController::DoAcquire() {} template void ResourceController::DoAfterAssignment() {} template void ResourceController::DoBeforeAssignment() {} template void ResourceController::DoRelease() {} // Access // Predicates // Static Variables /////////////////////////// PRIVATE ///////////////////////////////// // C'tors/D'tors // Operators // Operations // Access // Predicates // Static Variables /////////////////////////// HELPERS ///////////////////////////////// template bool operator==(ResourceController const &lhs, ResourceController const &rhs) { return lhs.m_Resource == rhs.m_Resource; } template bool operator!=(ResourceController const &lhs, ResourceController const &rhs) { return !operator==(lhs, rhs); } #endif // SLBCSP_RSRCCTRLR_H