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.
 
 
 
 
 
 

243 lines
6.4 KiB

// slbRCPtr.h -- 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_RCPTR_H)
#define SLB_RCPTR_H
#include "slbRCComp.h"
#include "slbRCObj.h"
namespace slbRefCnt {
// template class RCPtr -- Reference Counting Pointer
//
// The RCPtr template implements a variant of the "Counted Pointer"
// idiom. RCPtr is a reference counting smart pointer-to-T object
// where T must inherit from RCObject (reference counted objects, see
// slbRCObj.h).
//
// C is the comparator class to use in performing the pointer
// comparison operations, defaulting to 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.
//
// CONTRAINTS: RCPtr can only be used for reference counting those
// objects for which you have the source because RCPtr only reference
// objects derived from RCObject. See GRCPtr in slbGRCPtr.h for
// reference counting objects when you don't have access to the source
// of the class to reference count.
//
// 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 RCPtr
{
public:
// Types
typedef T ValueType;
// 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
RCPtr(T *pReal = 0);
RCPtr(RCPtr<T, C> const &rhs);
~RCPtr();
// Operators
RCPtr<T, C> &operator=(RCPtr<T, C> const &rhs);
// Enable validity test of RCPtr. See the explanation in
// slbRCComp.h.
operator PrivateDummy const *() const
{ return reinterpret_cast<PrivateDummy *>(m_pointee); }
// Access
T *operator->() const;
T &operator*() const;
private:
// Operations
void Init();
// Variables
T *m_pointee;
};
template<class T, typename C>
RCPtr<T, C>::RCPtr(T *pReal)
: m_pointee(pReal)
{
Init();
}
template<class T, typename C>
RCPtr<T, C>::RCPtr(RCPtr<T, C> const &rhs)
: m_pointee(rhs.m_pointee)
{
Init();
}
template<class T, typename C>
RCPtr<T, C>::~RCPtr()
{
try
{
if (m_pointee)
m_pointee->RemoveReference();
}
catch (...)
{
// don't allow exceptions to propagate out of destructor
}
}
template<class T, typename C>
RCPtr<T, C> &
RCPtr<T, C>::operator=(RCPtr<T, C> const &rhs)
{
if (m_pointee != rhs.m_pointee)
{
if (m_pointee)
m_pointee->RemoveReference();
m_pointee = rhs.m_pointee;
Init();
}
return *this;
}
template<class T, typename C>
T *
RCPtr<T, C>::operator->() const
{
return m_pointee;
}
template<class T, typename C>
T &
RCPtr<T, C>::operator*() const
{
return *m_pointee;
}
template<class T, typename C>
bool
operator==(RCPtr<T, C> const &lhs,
RCPtr<T, C> const &rhs)
{
C Comp;
return Comp.Equates(lhs.operator->(), rhs.operator->());
}
template<class T, typename C>
bool
operator!=(RCPtr<T, C> const &lhs,
RCPtr<T, C> const &rhs)
{
C Comp;
return !Comp.Equates(lhs.operator->(), rhs.operator->());
}
template<class T, typename C>
bool
operator<(RCPtr<T, C> const &lhs,
RCPtr<T, C> const &rhs)
{
C Comp;
return Comp.IsLess(lhs.operator->(), rhs.operator->());
}
template<class T, typename C>
bool
operator>(RCPtr<T, C> const &lhs,
RCPtr<T, C> const &rhs)
{
C Comp;
return Comp.IsLess(rhs.operator->(), lhs.operator->());
}
template<class T, typename C>
bool
operator<=(RCPtr<T, C> const &lhs,
RCPtr<T, C> const &rhs)
{
C Comp;
return !Comp.IsLess(rhs.operator->(), lhs.operator->());
}
template<class T, typename C>
bool
operator>=(RCPtr<T, C> const &lhs,
RCPtr<T, C> const &rhs)
{
C Comp;
return !Comp.IsLess(lhs.operator->(), rhs.operator->());
}
template<class T, typename C>
void
RCPtr<T, C>::Init()
{
if (m_pointee)
m_pointee->AddReference();
}
} // namespace
#endif // SLB_RCPTR_H