diff options
Diffstat (limited to 'include/EASTL/safe_ptr.h')
-rw-r--r-- | include/EASTL/safe_ptr.h | 485 |
1 files changed, 0 insertions, 485 deletions
diff --git a/include/EASTL/safe_ptr.h b/include/EASTL/safe_ptr.h deleted file mode 100644 index 344ded8..0000000 --- a/include/EASTL/safe_ptr.h +++ /dev/null @@ -1,485 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright (c) Electronic Arts Inc. All rights reserved. -/////////////////////////////////////////////////////////////////////////////// - - -#ifndef EASTL_SAFEPTR_H -#define EASTL_SAFEPTR_H - - -#include <EASTL/internal/config.h> -#include <stddef.h> - -#if defined(EA_PRAGMA_ONCE_SUPPORTED) - #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. -#endif - - - -namespace eastl -{ - class safe_ptr_base; - - - /// safe_object - /// - /// In order for a class to be the template argument for safe_ptr, - /// it must derive from safe_object. - /// - /// Example usage: - /// class RandomLifetimeObject : public safe_object - /// { - /// public: - /// RandomLifetimeObject(); - /// Method(); - /// ... - /// }; - /// - class safe_object - { - public: - bool is_unreferenced() const; /// Returns true if there are zero references (by a smart_ptr) to this object (mpSafePtrList is NULL). - bool has_unique_reference() const; /// Returns true if there is at most one reference (by a smart_ptr) to us. - - protected: - safe_object(); - ~safe_object(); - - void clear_references(); /// Forcibly removes any references (by smart_ptrs) to this object. All safe_ptr mpObject values are set to NULL. - - private: - friend class safe_ptr_base; - - void add(safe_ptr_base* pBase) const; /// Link pBase into my list of safe pointers. - void remove(safe_ptr_base* pBase) const; /// Unlink pBase from my list of safe pointers. - - mutable safe_ptr_base* mpSafePtrList; - - public: - // Deprecated, as its name is misleading: - bool has_references() const; /// Returns true if there is at most one reference (by a smart_ptr) to us. - }; - - - - /// safe_ptr_base - /// - /// This is a non-templated base class for safe_ptr<T>, not for direct use by the user. - /// - class safe_ptr_base - { - public: - bool unique() const; /// Returns true if there are no other smart pointers pointing to our object except us. True if mpObject is NUll - bool empty() const; /// Returns true if mpObject is NULL. - void reset(const safe_object* pObject); /// Make this point to pObject and enlist. - void reset(); /// Make this point to NULL and delist. - - protected: - // The following are protected and must be overridden in the safe_ptr<T> subclass. - safe_ptr_base(); - safe_ptr_base(const safe_object* pObject); - safe_ptr_base(const safe_ptr_base& safePtrBase); - ~safe_ptr_base(); - - protected: - const safe_object* mpObject; - - private: - friend class safe_object; - - safe_ptr_base& operator=(const safe_ptr_base& safePtrBase); - - safe_ptr_base* mpNext; - }; - - - /// safe_ptr - /// - /// safe_ptr is an automatic, lightweight solution to the dangling pointer problem. - /// This class is an alternative to weak_ptr which has the primary benefit of not - /// allocating memory at the primary cost of being a tad slower and thread-unsafe. - /// - /// During normal usage, safe_ptr<T> behaves exactly as a T*. When the - /// raw pointer referenced by the safe_ptr is deleted, all of the SafePtrs - /// for the raw pointer are set to NULL. - /// - /// This works by making the raw objects derive from the class safe_object, - /// which maintains a linked-list of the Safe pointers that reference it. - /// When a safe_object is destroyed, it walks its linked list, setting the - /// object reference for each of its SafePtrs to NULL. - /// - /// The overhead for this is light - a single pointer is added to the - /// size of the pointed to object, and a safePtr is the size of a raw - /// pointer plus one list pointer. - /// - /// This class is not thread-safe. In particular, manipulation of safe_ptr - /// objects that refer to the same underlying object cannot be done safely - /// from multiple threads. safe_ptr objects that are unrelated can be used - /// safely from multiple threads. - /// - /// Example usage: - /// class RandomLifetimeObject : public safe_object - /// { - /// public: - /// RandomLifetimeObject(); - /// Method(); - /// ... - /// }; - /// - /// safe_ptr<RandomLifetimeObject> pSafePtr(new RandomLifetimeObject); - /// safe_ptr<RandomLifetimeObject> pSafePtrCopy = pSafePtr; - /// - /// pSafePtr->Method(); - /// delete pSafePtr; - /// At this point, pSafePtrCopy evaluates to NULL. - /// - template<class T> - class safe_ptr : public safe_ptr_base - { - public: - typedef T value_type; - typedef safe_ptr<T> this_type; - - public: - safe_ptr(); /// Default constructor. - explicit safe_ptr(T* pObject); /// Construct a safeptr from a naked pointer. - safe_ptr(const this_type& safePtr); /// Copy constructor. - //~safe_ptr() {} /// No need to implement this; the compiler-generated destructor is OK. - - this_type& operator=(const this_type& safePtr); /// Assignment operator. - this_type& operator=(T* const pObject); /// Assign this to a naked pointer. - - bool operator==(const this_type& safePtr) const; /// Returns true if safePtr points to the same object as this. - - public: - T* get() const; /// Get the naked pointer from this safe ptr. - operator T*() const; /// Implicit safe_ptr<T> -> T* conversion operator. - T* operator->() const; /// Member operator. - T& operator*() const; /// Dereference operator. - bool operator!() const; /// Boolean negation operator. - - typedef T* (this_type::*bool_)() const; /// Allows for a more portable version of testing an instance of this class as a bool. - operator bool_() const // A bug in the CodeWarrior compiler forces us to implement this inline instead of below. - { - if(mpObject) - return &this_type::get; - return NULL; - } - }; - -} // namespace eastl - - - - - - -///////////////////////////////////////////////////////////////////////// -// Inlines -///////////////////////////////////////////////////////////////////////// - - -/////////////////////////////////////////////////////////////////////////////// -// safe_object -/////////////////////////////////////////////////////////////////////////////// - -inline eastl::safe_object::safe_object() - : mpSafePtrList(0) -{ -} - - -inline bool eastl::safe_object::is_unreferenced() const -{ - return (mpSafePtrList == NULL); -} - - -inline void eastl::safe_object::clear_references() -{ - while(mpSafePtrList != NULL) - { - safe_ptr_base* const pNext = mpSafePtrList->mpNext; - mpSafePtrList->mpNext = NULL; - mpSafePtrList->mpObject = NULL; - mpSafePtrList = pNext; - } -} - - -inline eastl::safe_object::~safe_object() -{ - safe_ptr_base* pIter = mpSafePtrList; - - while(pIter) - { - safe_ptr_base* const pNext = pIter->mpNext; - pIter->mpNext = NULL; - pIter->mpObject = NULL; - pIter = pNext; - } -} - - -inline void eastl::safe_object::add(safe_ptr_base* pBase) const -{ - pBase->mpNext = mpSafePtrList; - mpSafePtrList = pBase; -} - - -inline void eastl::safe_object::remove(safe_ptr_base* pBase) const -{ - // We have a singly-linked list (starting with mpSafePtrList) and need to - // remove an element from within it. - if(pBase == mpSafePtrList) - mpSafePtrList = mpSafePtrList->mpNext; - else - { - for(safe_ptr_base *pPrev = mpSafePtrList, *pCurrent = mpSafePtrList->mpNext; - pCurrent; - pPrev = pCurrent, pCurrent = pCurrent->mpNext) - { - if(pCurrent == pBase) - { - pPrev->mpNext = pCurrent->mpNext; - break; - } - } - } -} - - -/////////////////////////////////////////////////////////////////////////////// -// safe_ptr_base -/////////////////////////////////////////////////////////////////////////////// - -inline eastl::safe_ptr_base::safe_ptr_base(const safe_ptr_base& safePtrBase) - : mpObject(safePtrBase.mpObject), - mpNext(NULL) -{ - EASTL_ASSERT(this != &safePtrBase); - - if(mpObject) - mpObject->add(this); -} - - -inline eastl::safe_ptr_base::safe_ptr_base() - : mpObject(NULL), - mpNext(NULL) -{ -} - - -inline eastl::safe_ptr_base::safe_ptr_base(const safe_object* pObject) - : mpObject(pObject), - mpNext(NULL) -{ - if(mpObject) - mpObject->add(this); -} - - -inline eastl::safe_ptr_base::~safe_ptr_base() -{ - if(mpObject) - mpObject->remove(this); -} - - -inline void eastl::safe_ptr_base::reset() -{ - if(mpObject) - { - mpObject->remove(this); - mpObject = NULL; - } -} - - -inline bool eastl::safe_ptr_base::empty() const -{ - return (mpObject == NULL); -} - - -inline void eastl::safe_ptr_base::reset(const safe_object* pNewObject) -{ - if(mpObject != pNewObject) - { - if(mpObject) - mpObject->remove(this); - - mpObject = pNewObject; - - if(mpObject) - mpObject->add(this); - } -} - - -inline bool eastl::safe_ptr_base::unique() const -{ - return (mpNext == NULL) && ((mpObject == NULL) || (mpObject->mpSafePtrList == this)); -} - - - -/////////////////////////////////////////////////////////////////////////////// -// safe_object -/////////////////////////////////////////////////////////////////////////////// - - -// This function is defined here below safe_ptr_base because some compilers -// (GCC in particular) generate warnings about inline functions (e.g. unique below) -// being used before their inline implementations. -inline bool eastl::safe_object::has_unique_reference() const -{ - return mpSafePtrList ? mpSafePtrList->unique() : false; -} - -// Deprecated: -inline bool eastl::safe_object::has_references() const -{ - return mpSafePtrList ? mpSafePtrList->unique() : false; -} - - -/////////////////////////////////////////////////////////////////////////////// -// safe_ptr<T> -/////////////////////////////////////////////////////////////////////////////// - -template<class T> -inline eastl::safe_ptr<T>::safe_ptr() - : safe_ptr_base() -{ -} - - -template<class T> -inline eastl::safe_ptr<T>::safe_ptr(T* pObject) - : safe_ptr_base(pObject) -{ -} - - -template<class T> -inline eastl::safe_ptr<T>::safe_ptr(const this_type& safePtr) - : safe_ptr_base(safePtr) -{ -} - - -template<class T> -inline typename eastl::safe_ptr<T>::this_type& eastl::safe_ptr<T>::operator=(const this_type& safePtr) -{ - if(this != &safePtr) - reset(safePtr.mpObject); - return *this; -} - - -template<class T> -inline typename eastl::safe_ptr<T>::this_type& eastl::safe_ptr<T>::operator=(T* const pObject) -{ - reset(pObject); - return *this; -} - - -template<class T> -inline bool eastl::safe_ptr<T>::operator==(const this_type& rhs) const -{ - return (mpObject == rhs.mpObject); -} - - -template<class T> -inline T* eastl::safe_ptr<T>::get() const -{ - return static_cast<T*>(const_cast<safe_object*>(mpObject)); -} - - -template<class T> -inline eastl::safe_ptr<T>::operator T*() const -{ - return static_cast<T*>(const_cast<safe_object*>(mpObject)); -} - - -template<class T> -inline T* eastl::safe_ptr<T>::operator->() const -{ - return static_cast<T*>(const_cast<safe_object*>(mpObject)); -} - - -template<class T> -inline T& eastl::safe_ptr<T>::operator*() const -{ - return *static_cast<T*>(const_cast<safe_object*>(mpObject)); -} - - -template<class T> -inline bool eastl::safe_ptr<T>::operator!() const -{ - return (mpObject == NULL); -} - -// A bug in the CodeWarrior compiler forces us to implement this inline in the class instead of here. -// template<class T> -// inline eastl::safe_ptr<T>::operator bool_() const -// { -// if(mpObject) -// return &this_type::get; -// return NULL; -// } - - - -/////////////////////////////////////////////////////////////////////////////// -// global operators -/////////////////////////////////////////////////////////////////////////////// - -template<class T> -inline bool operator==(const eastl::safe_ptr<T>& safePtr, const T* pObject) -{ - return (safePtr.get() == pObject); -} - - -template<class T> -inline bool operator!=(const eastl::safe_ptr<T>& safePtr, const T* pObject) -{ - return (safePtr.get() != pObject); -} - - -template<class T> -inline bool operator<(const eastl::safe_ptr<T>& safePtrA, const eastl::safe_ptr<T>& safePtrB) -{ - return (safePtrA.get() < safePtrB.get()); -} - - - - -#endif // Header include guard - - - - - - - - - - - - - - - |