mirror of https://github.com/tongzx/nt5src
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
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
|