Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

260 lines
7.5 KiB

// slbGRCPtr.h -- Generic Reference counting smart pointer.
// (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(SLB_GRCPTR_H)
#define SLB_GRCPTR_H
#include "slbRCComp.h"
#include "slbRCObj.h"
namespace slbRefCnt {
// template class GRCPtr -- Generic Reference Counting Pointer
//
// GRCPtr is a template class that implements a variant of the
// "Counted Pointer" idiom. GRCPtr is a reference counting smart
// pointer-to-T object where T can be any class. GRCPtr provides a
// "wrapper" to encapsulate reference counting of any object without
// having to modify the class of the object being referenced. This
// would be used when you can't change the class T to be derived from
// RCObject (reference counted objects, see slbRCObject.h); otherwise
// the RCPtr template may be better (see slbRCPtr.h).
//
// C is the comparator class to use in performing the pointer
// comparison operations. The template defaults to the
// ShallowComparator. See slbRComp.h for more information.
//
// The template's original design was inspired by the reference
// counting idiom described by Item #29 in the book "More Effective
// C++," Scott Meyers, Addison-Wesley, 1996.
//
// CONSTRAINTS: RCPtr should not be used as a base class.
//
// CAVEATS: The client should not use the Dummy * conversion
// operator. The definition allows smart pointer comparisons. See
// slbRCComp.h for more information.
template<class T, typename C = ShallowComparator<T> >
class GRCPtr
{
public:
// Types
// PrivateDummy is a helper class to support validity testing of a
// pointer. This class together with the conversion operator
// PrivateDummy const *() below allows smart pointers to be tested
// for nullness (validity tests). In other words, comparing
// pointers in a syntactically natural way without allowing
// heterogeneous comparisons and that won't violate the
// protections that RCPtr provides. The technique is from an
// article by Don Box in "Com Smart Pointers Also Considered
// Harmful," 1996, C++ Report.
//
// CAVEAT: There is a defect in the at least with MSVC++ 6.0 where
// constructs testing the pointer for nullness will fail to
// compile with a error message in the Release configuration but
// compile successfully in Debug. For example,
//
// if (p) ...
//
// where p is an RCPtr or GRCPtr may fail to compile in the
// Release configuration.
//
// CAVEAT: Although the PrivateDummy and the conversion operator
// has public access to the pointer of the object being counted
// (RCObject *), a C-style or reinterpret_cast cast would have to
// be used. As in all cases using those cast
// constructs--programmer beware.
//
// DESIGN NOTE: The helper class is functionally the same as the
// one in the RCPtr template. In a previous release, this dummy
// class was made into a template and shared with both RCPtr and
// GRCPtr. However, casual compilation tests with MSVC++ 6.0 indicate
// compilation with a dummy local to each class resulted in
// noticable faster compilations using a test suite. Rather than
// suffer repeatedly slower compilations, the helper was made
// local to each user.
class PrivateDummy
{};
// Constructors/Destructors
GRCPtr(T *pReal = 0);
GRCPtr(GRCPtr<T, C> const &rhs);
~GRCPtr();
// Operators
GRCPtr<T, C> &operator=(GRCPtr<T, C> const &rhs);
// Not for direct client use. This conversion operator enables
// validity test of RGCPtr. See the explanation of PrivateDummy
// above.
operator PrivateDummy const *() const
{ return reinterpret_cast<PrivateDummy *>(m_holder->m_pointee); }
// Access
T *operator->();
T &operator*();
private:
// Operations
void Init();
// Variables
struct Holder : public RCObject
{
~Holder() { delete m_pointee; }
T *m_pointee;
};
Holder *m_holder;
// Friends
// The friendship is necessary to get m_pointee, since
// using operator-> doesn't work. Curiously, a similar frienship
// is not needed for RCPtrs.
friend bool operator==(GRCPtr<T, C> const &lhs,
GRCPtr<T, C> const &rhs);
friend bool operator!=(GRCPtr<T, C> const &lhs,
GRCPtr<T, C> const &rhs);
friend bool operator<(GRCPtr<T, C> const &lhs,
GRCPtr<T, C> const &rhs);
friend bool operator>(GRCPtr<T, C> const &lhs,
GRCPtr<T, C> const &rhs);
friend bool operator<=(GRCPtr<T, C> const &lhs,
GRCPtr<T, C> const &rhs);
friend bool operator>=(GRCPtr<T, C> const &lhs,
GRCPtr<T, C> const &rhs);
};
template<class T, typename C>
GRCPtr<T, C>::GRCPtr(T *pReal)
: m_holder(new Holder)
{
m_holder->m_pointee = pReal;
Init();
}
template<class T, typename C>
GRCPtr<T, C>::GRCPtr(GRCPtr<T, C> const &rhs)
: m_holder(rhs.m_holder)
{
Init();
}
template<class T, typename C>
GRCPtr<T, C>::~GRCPtr()
{
try
{
m_holder->RemoveReference();
}
catch (...)
{
// don't allow exceptions to propagate out of destructor
}
}
template<class T, typename C>
GRCPtr<T, C> &
GRCPtr<T, C>::operator=(GRCPtr<T, C> const &rhs)
{
if (m_holder != rhs.m_holder)
{
m_holder->RemoveReference();
m_holder = rhs.m_holder;
Init();
}
return *this;
}
template<class T, typename C>
T *
GRCPtr<T, C>::operator->()
{
return m_holder->m_pointee;
}
template<class T, typename C>
T &
GRCPtr<T, C>::operator*()
{
return *(m_holder->m_pointee);
}
template<class T, typename C>
void
GRCPtr<T, C>::Init()
{
m_holder->AddReference();
}
template<class T, typename C>
bool
operator==(GRCPtr<T, C> const &lhs,
GRCPtr<T, C> const &rhs)
{
C Comp;
return Comp.Equates(lhs.m_holder->m_pointee, rhs.m_holder->m_pointee);
}
template<class T, typename C>
bool
operator!=(GRCPtr<T, C> const &lhs,
GRCPtr<T, C> const &rhs)
{
C Comp;
return !Comp.Equates(lhs.m_holder->m_pointee, rhs.m_holder->m_pointee);
}
template<class T, typename C>
bool
operator<(GRCPtr<T, C> const &lhs,
GRCPtr<T, C> const &rhs)
{
C Comp;
return Comp.IsLess(lhs.m_holder->m_pointee, rhs.m_holder->m_pointee);
}
template<class T, typename C>
bool
operator>(GRCPtr<T, C> const &lhs,
GRCPtr<T, C> const &rhs)
{
C Comp;
return Comp.IsLess(rhs.m_holder->m_pointee, lhs.m_holder->m_pointee);
}
template<class T, typename C>
bool
operator<=(GRCPtr<T, C> const &lhs,
GRCPtr<T, C> const &rhs)
{
C Comp;
return !Comp.IsLess(rhs.m_holder->m_pointee, lhs.m_holder->m_pointee);
}
template<class T, typename C>
bool
operator>=(GRCPtr<T, C> const &lhs,
GRCPtr<T, C> const &rhs)
{
C Comp;
return !Comp.IsLess(lhs.m_holder->m_pointee, rhs.m_holder->m_pointee);
}
} // namespace
#endif // SLB_GRCPTR_H