www.pudn.com > Loki.rar > 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: May 19, 2002 
 
#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 
    { 
    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  
        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&, bool = false) 
        { 
            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