📄 smartptr.h
字号:
////////////////////////////////////////////////////////////////////////////////
// The Loki Library
// Copyright (c) 2001 by Andrei Alexandrescu
// This code accompanies the book:
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
// Permission to use, copy, modify, distribute and sell this software for any
// purpose is hereby granted without fee, provided that the above copyright
// notice appear in all copies and that both that copyright notice and this
// permission notice appear in supporting documentation.
// The author or Addison-Welsey Longman make no representations about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////
// Last update: June 20, 2001
#ifndef SMARTPTR_INC_
#define SMARTPTR_INC_
////////////////////////////////////////////////////////////////////////////////
// IMPORTANT NOTE
// Due to threading issues, the OwnershipPolicy has been changed as follows:
// Release() returns a boolean saying if that was the last release
// so the pointer can be deleted by the StoragePolicy
// IsUnique() was removed
////////////////////////////////////////////////////////////////////////////////
#include "SmallObj.h"
#include "TypeManip.h"
#include "static_check.h"
#include <functional>
#include <stdexcept>
namespace Loki
{
////////////////////////////////////////////////////////////////////////////////
// class template DefaultSPStorage
// Implementation of the StoragePolicy used by SmartPtr
////////////////////////////////////////////////////////////////////////////////
template <class T>
class DefaultSPStorage
{
protected:
typedef T* StoredType; // the type of the pointee_ object
typedef T* PointerType; // type returned by operator->
typedef T& ReferenceType; // type returned by operator*
public:
DefaultSPStorage() : pointee_(Default())
{}
// The storage policy doesn't initialize the stored pointer
// which will be initialized by the OwnershipPolicy's Clone fn
DefaultSPStorage(const DefaultSPStorage&)
{}
template <class U>
DefaultSPStorage(const DefaultSPStorage<U>&)
{}
DefaultSPStorage(const StoredType& p) : pointee_(p) {}
PointerType operator->() const { return pointee_; }
ReferenceType operator*() const { return *pointee_; }
void Swap(DefaultSPStorage& rhs)
{ std::swap(pointee_, rhs.pointee_); }
// Accessors
friend inline PointerType GetImpl(const DefaultSPStorage& sp)
{ return sp.pointee_; }
friend inline const StoredType& GetImplRef(const DefaultSPStorage& sp)
{ return sp.pointee_; }
friend inline StoredType& GetImplRef(DefaultSPStorage& sp)
{ return sp.pointee_; }
protected:
// Destroys the data stored
// (Destruction might be taken over by the OwnershipPolicy)
void Destroy()
{ delete pointee_; }
// Default value to initialize the pointer
static StoredType Default()
{ return 0; }
private:
// Data
StoredType pointee_;
};
////////////////////////////////////////////////////////////////////////////////
// class template RefCounted
// Implementation of the OwnershipPolicy used by SmartPtr
// Provides a classic external reference counting implementation
////////////////////////////////////////////////////////////////////////////////
template <class P>
class RefCounted
{
public:
RefCounted()
{
pCount_ = static_cast<unsigned int*>(
SmallObject<>::operator new(sizeof(unsigned int)));
assert(pCount_);
*pCount_ = 1;
}
RefCounted(const RefCounted& rhs)
: pCount_(rhs.pCount_)
{}
// MWCW lacks template friends, hence the following kludge
template <typename P1>
RefCounted(const RefCounted<P1>& rhs)
: pCount_(reinterpret_cast<const RefCounted&>(rhs).pCount_)
{}
P Clone(const P& val)
{
++*pCount_;
return val;
}
bool Release(const P&)
{
if (!--*pCount_)
{
SmallObject<>::operator delete(pCount_, sizeof(unsigned int));
return true;
}
return false;
}
void Swap(RefCounted& rhs)
{ std::swap(pCount_, rhs.pCount_); }
enum { destructiveCopy = false };
private:
// Data
unsigned int* pCount_;
};
////////////////////////////////////////////////////////////////////////////////
// class template RefCountedMT
// Implementation of the OwnershipPolicy used by SmartPtr
// Implements external reference counting for multithreaded programs
////////////////////////////////////////////////////////////////////////////////
template <class P,
template <class> class ThreadingModel>
class RefCountedMT : public ThreadingModel< RefCountedMT<P, ThreadingModel> >
{
public:
RefCountedMT()
{
pCount_ = static_cast<unsigned int*>(
SmallObject<ThreadingModel>::operator new(
sizeof(unsigned int)));
assert(pCount_);
*pCount_ = 1;
}
RefCountedMT(const RefCountedMT& rhs)
: pCount_(rhs.pCount_)
{}
// MWCW lacks template friends, hence the following kludge
template <typename P1>
RefCountedMT(const RefCountedMT<P1, ThreadingModel>& rhs)
: pCount_(reinterpret_cast<const RefCounted<P>&>(rhs).pCount_)
{}
P Clone(const P& val)
{
ThreadingModel<RefCountedMT>::AtomicIncrement(*pCount_);
return val;
}
bool Release(const P&)
{
if (!ThreadingModel<RefCountedMT>::AtomicDecrement(*pCount_))
{
SmallObject<ThreadingModel>::operator delete(pCount_,
sizeof(unsigned int));
return true;
}
return false;
}
void Swap(RefCountedMT& rhs)
{ std::swap(pCount_, rhs.pCount_); }
enum { destructiveCopy = false };
private:
// Data
volatile unsigned int* pCount_;
};
////////////////////////////////////////////////////////////////////////////////
// class template COMRefCounted
// Implementation of the OwnershipPolicy used by SmartPtr
// Adapts COM intrusive reference counting to OwnershipPolicy-specific syntax
////////////////////////////////////////////////////////////////////////////////
template <class P>
class COMRefCounted
{
public:
COMRefCounted()
{}
template <class U>
COMRefCounted(const COMRefCounted<U>&)
{}
static P Clone(const P& val)
{
val->AddRef();
return val;
}
static bool Release(const P& val)
{ val->Release(); return false; }
enum { destructiveCopy = false };
static void Swap(COMRefCounted&)
{}
};
////////////////////////////////////////////////////////////////////////////////
// class template DeepCopy
// Implementation of the OwnershipPolicy used by SmartPtr
// Implements deep copy semantics, assumes existence of a Clone() member
// function of the pointee type
////////////////////////////////////////////////////////////////////////////////
template <class P>
struct DeepCopy
{
DeepCopy()
{}
template <class P1>
DeepCopy(const DeepCopy<P1>&)
{}
static P Clone(const P& val)
{ return val->Clone(); }
static bool Release(const P& val)
{ return true; }
static void Swap(DeepCopy&)
{}
enum { destructiveCopy = false };
};
////////////////////////////////////////////////////////////////////////////////
// class template RefLinked
// Implementation of the OwnershipPolicy used by SmartPtr
// Implements reference linking
////////////////////////////////////////////////////////////////////////////////
namespace Private
{
class RefLinkedBase
{
public:
RefLinkedBase()
{ prev_ = next_ = this; }
RefLinkedBase(const RefLinkedBase& rhs)
{
prev_ = &rhs;
next_ = rhs.next_;
prev_->next_ = this;
next_->prev_ = this;
}
bool Release()
{
if (next_ == this)
{
assert(prev_ == this);
return true;
}
prev_->next_ = next_;
next_->prev_ = prev_;
return false;
}
void Swap(RefLinkedBase& rhs)
{
if (next_ == this)
{
assert(prev_ == this);
if (rhs.next_ == &rhs)
{
assert(rhs.prev_ == &rhs);
// both lists are empty, nothing 2 do
return;
}
prev_ = rhs.prev_;
next_ = rhs.next_;
prev_->next_ = next_->prev_ = this;
rhs.next_ = rhs.prev_ = &rhs;
return;
}
if (rhs.next_ == &rhs)
{
rhs.Swap(*this);
return;
}
std::swap(prev_, rhs.prev_);
std::swap(next_, rhs.next_);
std::swap(prev_->next_, rhs.prev_->next_);
std::swap(next_->prev_, rhs.next_->prev_);
}
enum { destructiveCopy = false };
private:
mutable const RefLinkedBase* prev_;
mutable const RefLinkedBase* next_;
};
}
template <class P>
class RefLinked : public Private::RefLinkedBase
{
public:
RefLinked()
{}
template <class P1>
RefLinked(const RefLinked<P1>& rhs)
: Private::RefLinkedBase(rhs)
{}
static P Clone(const P& val)
{ return val; }
bool Release(const P&)
{ return Private::RefLinkedBase::Release(); }
};
////////////////////////////////////////////////////////////////////////////////
// class template DestructiveCopy
// Implementation of the OwnershipPolicy used by SmartPtr
// Implements destructive copy semantics (a la std::auto_ptr)
////////////////////////////////////////////////////////////////////////////////
template <class P>
class DestructiveCopy
{
public:
DestructiveCopy()
{}
template <class P1>
DestructiveCopy(const DestructiveCopy<P1>&)
{}
template <class P1>
static P Clone(P1& val)
{
P result(val);
val = P1();
return result;
}
static bool Release(const P&)
{ return true; }
static void Swap(DestructiveCopy&)
{}
enum { destructiveCopy = true };
};
////////////////////////////////////////////////////////////////////////////////
// class template NoCopy
// Implementation of the OwnershipPolicy used by SmartPtr
// Implements a policy that doesn't allow copying objects
////////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -