⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smartptr.h

📁 loki 程序库
💻 H
📖 第 1 页 / 共 3 页
字号:
////////////////////////////////////////////////////////////////////////////////
// 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.
////////////////////////////////////////////////////////////////////////////////

// Last update: Mar 06, 2003

// ported RefCountedMT
// To create a SmartPtr with RefCountedMT as ownership policy
// use code like this:
// SmartPtr<Foo, RefCountedMTWrapper<ClassLevelLockable> > pointer;
//
// replaced all template template parameters with 'normal' parameters
// For each Policy there is now a wrapper-class (non template class) 
// containing a nested template class called In which
// provides a typedef (type) to the real Policy-class
// 
// VC special: The MSVC 6.0 introduces an order-dependency for template ctor 
// resp. template assignemt operators. 
// If you need both a copy-ctor and a template copy ctor (same for copy-assignment), then
// you *must* write the templated version first.
// So instead of
//	template <class T>
//	struct Foo
//	{
//		Foo(const Foo&)
//		{}
//		template <class U>
//		Foo(const Foo<U>& r)
//		{}
//	};
// you *need* to write:
//	template <class T>
//	struct Foo
//	{
//		template <class U>
//		Foo(const Foo<U>& r)
//		{}
//		
//		Foo(const Foo& r)
//		{}
//	};
//
// Many thanks to Nelson El骾 for pointing that out and for providing me
// with this solution


#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 "MSVC6Helpers.h"
#include "static_check.h"
#include <functional>
#include <stdexcept>
#include <cassert>

namespace Loki
{
////////////////////////////////////////////////////////////////////////////////
// class template DefaultSPStorage
// Implementation of the StoragePolicy used by SmartPtr
////////////////////////////////////////////////////////////////////////////////
	
    template <class T>
    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*
        
    public:
        DefaultSPStorage() : pointee_(Default()) 
        {}

        // The storage policy doesn't initialize the stored pointer 
        //     which will be initialized by the OwnershipPolicy's Clone fn
		
		// do not alter the order of the following two constructors
		// otherwise the MSVC 6.0 will not compile the class.
		template <class U>
		DefaultSPStorage(const DefaultSPStorage<U>&)  {}

		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_;
    };
	
	struct DefaultSPStorageWrapper
	{
		template <class T>
		struct In
		{
			typedef DefaultSPStorage<T> type;
		};
	};
    
////////////////////////////////////////////////////////////////////////////////
// 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;
        }
        
		// do not alter the order of the following two constructors
		// otherwise the MSVC 6.0 will fail to compile the class.

		// MWCW lacks template friends, hence the following kludge
        template <typename P1>
        RefCounted(const RefCounted<P1>& rhs) 
        : pCount_(reinterpret_cast<const RefCounted&>(rhs).pCount_)
        {}

		RefCounted(const RefCounted& rhs) 
        : pCount_(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_;
    };
    

	struct RefCountedWrapper
	{
		template<class T>
		struct In
		{
			typedef RefCounted<T> type;
		};
	};
////////////////////////////////////////////////////////////////////////////////
// class template RefCountedMT
// Implementation of the OwnershipPolicy used by SmartPtr
// Implements external reference counting for multithreaded programs
////////////////////////////////////////////////////////////////////////////////
//	

	template <class P, class ThreadingModel>
	class RefCountedMT : public Apply1<ThreadingModel, RefCountedMT<P, ThreadingModel> >
    {
    public:
		typedef Apply1<ThreadingModel, RefCountedMT<P, ThreadingModel> > base_type;
		typedef typename base_type::IntType       CountType;
        typedef volatile CountType               *CountPtrType;
		RefCountedMT() 
        {
            pCount_ = static_cast<CountPtrType>(
                SmallObject<ThreadingModel>::operator new(
                    sizeof(unsigned int)));
            assert(pCount_);
            *pCount_ = 1;
        }
        
		// MWCW lacks template friends, hence the following kludge
        // BK: Without the dummy-Parameter, the VC 6.0 won't compile the
		// copy ctor (error C2535: 'member function already defined or declared')
		// Adding the dummy-Parameter results in two things:
		// 1. The VC doesn't complain about the copy-ctor
		// 2. The VC *always* calls the template-copy-ctor, whether *this and rhs
		// have the same type or not.
		template <typename P1>
        RefCountedMT(const RefCountedMT<P1, ThreadingModel>& rhs, int dummy=0) 
        : pCount_(reinterpret_cast<const RefCountedMT<P, ThreadingModel>&>(rhs).pCount_)
        {}
        
		
		RefCountedMT(const RefCountedMT& rhs) 
        : pCount_(rhs.pCount_)
        {}
		
        
        
        P Clone(const P& val)
        {
			ThreadingModel::template In<RefCountedMT>::AtomicIncrement(*pCount_);
            return val;
        }
        
        bool Release(const P&)
        {
            if (!ThreadingModel::template In<RefCountedMT>::AtomicDecrement(*pCount_))
			{
				SmallObject<ThreadingModel>::operator delete(
                        const_cast<CountType *>(pCount_), 
                        sizeof(*pCount_));
				return true;
			}
			return false;
        }
        
        void Swap(RefCountedMT& rhs)
        { std::swap(pCount_, rhs.pCount_); }
    
        enum { destructiveCopy = false };

    private:
        // Data
        //volatile unsigned int* pCount_;
		CountPtrType pCount_;
    };	

	template <class ThreadingModel>
	struct RefCountedMTWrapper
	{
		template <class U>
		struct In
		{
			typedef RefCountedMT<U, ThreadingModel> type;
		};
	};
////////////////////////////////////////////////////////////////////////////////
// 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&)
        {}
    };
	
	struct COMRefCountedWrapper
	{
		template <class T>
		struct In
		{
			typedef COMRefCounted<T> type;
		};
	};
////////////////////////////////////////////////////////////////////////////////
// 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 };
    };

	struct DeepCopyWrapper
	{
		template <class T>
		struct In
		{
			typedef DeepCopy<T> type;
		};
	};
////////////////////////////////////////////////////////////////////////////////
// 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&)
        {	typedef Private::RefLinkedBase MyBase;
			return this->MyBase::Release(); 
		}
    };
	
	struct RefLinkedWrapper
	{
		template <class T>
		struct In
		{
			typedef RefLinked<T> type;
		};
	};
////////////////////////////////////////////////////////////////////////////////
// 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)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -