//////////////////////////////////////////////////////////////////////////////// // 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-Wesley Longman make no representations about the // suitability of this software for any purpose. It is provided "as is" // without express or implied warranty. //////////////////////////////////////////////////////////////////////////////// #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 #include #include namespace Loki { //////////////////////////////////////////////////////////////////////////////// // class template DefaultSPStorage // Implementation of the StoragePolicy used by SmartPtr //////////////////////////////////////////////////////////////////////////////// template class DefaultSPStorage { public: typedef T* StoredType; // the type of the pointee_ object typedef T* PointerType; // type returned by operator-> typedef T& ReferenceType; // type returned by operator* 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 DefaultSPStorage(const DefaultSPStorage&) {} 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 RefCounted { public: RefCounted() { pCount_ = static_cast( 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 RefCounted(const RefCounted& rhs) : pCount_(reinterpret_cast(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 // Policy Usage: RefCountedMTAdj::RefCountedMT //////////////////////////////////////////////////////////////////////////////// template