diff options
Diffstat (limited to 'include/EASTL/linked_ptr.h')
-rw-r--r-- | include/EASTL/linked_ptr.h | 426 |
1 files changed, 0 insertions, 426 deletions
diff --git a/include/EASTL/linked_ptr.h b/include/EASTL/linked_ptr.h deleted file mode 100644 index f57681a..0000000 --- a/include/EASTL/linked_ptr.h +++ /dev/null @@ -1,426 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Copyright (c) Electronic Arts Inc. All rights reserved. -/////////////////////////////////////////////////////////////////////////////// - - -#ifndef EASTL_LINKED_PTR_H -#define EASTL_LINKED_PTR_H - - - -#include <EASTL/internal/config.h> -#include <EASTL/internal/smart_ptr.h> // Defines smart_ptr_deleter -#include <EASTL/allocator.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 -{ - - /// linked_ptr_base - /// - /// This class allows linked_ptr<T> and linked_ptr<U> to share the same - /// base nodes and thus be in the same linked list. - /// - struct linked_ptr_base - { - mutable linked_ptr_base* mpPrev; - mutable linked_ptr_base* mpNext; - }; - - - /// linked_ptr - /// - /// This class implements a linked_ptr template. A linked_ptr is like the C++ - /// Standard Library auto_ptr except that it allows sharing of pointers between - /// instances of auto_ptr via reference counting. linked_ptr objects can safely - /// be copied and can safely be used in C++ Standard Library containers such - /// as std::vector or std::list. This implementation, however, is not thread-safe. - /// you would need to use a separate linked_ptr_mt (multi-threaded) to get - /// thread safety. - /// - /// linked_ptr is a variation of shared_ptr (a.k.a. counted_ptr) which differs - /// in that instead of being implemented by a shared integer stored on the heap, - /// it is implemented by linked list stored within the linked_ptr object itself. - /// The result is that no memory is explicitly allocated from the heap, though - /// the cost of each linked_ptr object is 12 bytes of memory (32 bit machine) - /// instead of 4 bytes for the case of shared_ptr (depending on the heap). - /// - template <typename T, typename Deleter = smart_ptr_deleter<T> > - class linked_ptr : public linked_ptr_base - { - protected: - template <typename U, typename D> friend class linked_ptr; - - /// this_type - /// This is an alias for linked_ptr<T>, this class. - typedef linked_ptr<T> this_type; - - /// deleter_type - typedef Deleter deleter_type; - - T* mpValue; /// The owned pointer. - - template <typename U, typename D> - void link(const linked_ptr<U, D>& linkedPtr) - { // This code can only be called when we are in a reset state. - // assert(!mpValue && (mpNext == mpPrev)); - mpNext = linkedPtr.mpNext; - mpNext->mpPrev = this; - mpPrev = const_cast<linked_ptr<U, D>*>(&linkedPtr); - linkedPtr.mpNext = this; - } - - public: - /// element_type - /// Synonym for type T, useful for external code to reference the - /// type in a generic way. - typedef T element_type; - - - /// linked_ptr - /// Default constructor. - linked_ptr() - : mpValue(NULL) - { - mpPrev = mpNext = this; - } - - - /// linked_ptr - /// Takes ownership of the pointer. It is OK if the input pointer is null. - template <typename U> - explicit linked_ptr(U* pValue) - : mpValue(pValue) - { - mpPrev = mpNext = this; - } - - - /// linked_ptr - /// Construction with self type. - /// If we want a shared_ptr constructor that is templated on linked_ptr<U>, - /// then we need to make it in addition to this function, as otherwise - /// the compiler will generate this function and things will go wrong. - linked_ptr(const linked_ptr& linkedPtr) - : mpValue(linkedPtr.mpValue) - { - if(mpValue) - link(linkedPtr); - else - mpPrev = mpNext = this; - } - - - /// linked_ptr - /// Shares ownership of a pointer with another instance of linked_ptr. - template <typename U, typename D> - linked_ptr(const linked_ptr<U, D>& linkedPtr) - : mpValue(linkedPtr.mpValue) - { - if(mpValue) - link(linkedPtr); - else - mpPrev = mpNext = this; - } - - - /// ~linked_ptr - /// Removes this object from the of objects using the shared pointer. - /// If this object is the last owner of the shared pointer, the shared - /// pointer is deleted. - ~linked_ptr() - { - reset(); - } - - - /// operator= - /// If we want a shared_ptr operator= that is templated on linked_ptr<U>, - /// then we need to make it in addition to this function, as otherwise - /// the compiler will generate this function and things will go wrong. - linked_ptr& operator=(const linked_ptr& linkedPtr) - { - if(linkedPtr.mpValue != mpValue) - { - reset(linkedPtr.mpValue); - if(linkedPtr.mpValue) - link(linkedPtr); - } - return *this; - } - - - /// operator= - /// Copies another linked_ptr to this object. Note that this object - /// may already own a shared pointer with another different pointer - /// (but still of the same type) before this call. In that case, - /// this function removes ownership of the old pointer and takes shared - /// ownership of the new pointer and increments its reference count. - template <typename U, typename D> - linked_ptr& operator=(const linked_ptr<U, D>& linkedPtr) - { - if(linkedPtr.mpValue != mpValue) - { - reset(linkedPtr.mpValue); - if(linkedPtr.mpValue) - link(linkedPtr); - } - return *this; - } - - - /// operator= - /// Assigns a new pointer. If the new pointer is equivalent - /// to the current pointer, nothing is done. Otherwise the - /// current pointer is unlinked and possibly destroyed. - /// The new pointer can be NULL. - template <typename U> - linked_ptr& operator=(U* pValue) - { - reset(pValue); - return *this; - } - - - /// reset - /// Releases the owned pointer and takes ownership of the - /// passed in pointer. If the passed in pointer is the same - /// as the owned pointer, nothing is done. The passed in pointer - /// can be NULL, in which case the use count is set to 1. - template <typename U> - void reset(U* pValue) - { - if(pValue != mpValue) - { - if(unique()) - { - deleter_type del; - del(mpValue); - } - else - { - mpPrev->mpNext = mpNext; - mpNext->mpPrev = mpPrev; - mpPrev = mpNext = this; - } - mpValue = pValue; - } - } - - - /// reset - /// Resets the container with NULL. If the current pointer - /// is non-NULL, it is unlinked and possibly destroyed. - void reset() - { - reset((T*)NULL); - } - - - /// swap - /// Exchanges the owned pointer beween two linkedPtr objects. - /// - /// This function is disabled as it is currently deemed unsafe. - /// The problem is that the only way to implement this function - /// is to transfer pointers between the objects; you cannot - /// transfer the linked list membership between the objects. - /// Thus unless both linked_ptr objects were 'unique()', the - /// shared pointers would be duplicated amongst containers, - /// resulting in a crash. - //template <typename U, typename D> - //void swap(linked_ptr<U, D>& linkedPtr) - //{ - // if(linkedPtr.mpValue != mpValue) - // { // This is only safe if both linked_ptrs are unique(). - // linkedPtr::element_type* const pValueTemp = linkedPtr.mpValue; - // linkedPtr.reset(mpValue); - // reset(pValueTemp); - // } - //} - - - /// operator* - /// Returns the owner pointer dereferenced. - T& operator*() const - { - return *mpValue; - } - - - /// operator-> - /// Allows access to the owned pointer via operator->() - T* operator->() const - { - return mpValue; - } - - - /// get - /// Returns the owned pointer. Note that this class does - /// not provide an operator T() function. This is because such - /// a thing (automatic conversion) is deemed unsafe. - T* get() const - { - return mpValue; - } - - - /// use_count - /// Returns the use count of the shared pointer. - /// The return value is one if the owned pointer is null. - /// This function is provided for compatibility with the - /// proposed C++ standard and for debugging purposes. It is not - /// intended for runtime use given that its execution time is - /// not constant. - int use_count() const - { - int useCount(1); - - for(const linked_ptr_base* pCurrent = static_cast<const linked_ptr_base*>(this); - pCurrent->mpNext != static_cast<const linked_ptr_base*>(this); pCurrent = pCurrent->mpNext) - ++useCount; - - return useCount; - } - - - /// unique - /// Returns true if the use count of the owned pointer is one. - /// The return value is true if the owned pointer is null. - bool unique() const - { - return (mpNext == static_cast<const linked_ptr_base*>(this)); - } - - - /// Implicit operator bool - /// Allows for using a linked_ptr as a boolean. - /// Note that below we do not use operator bool(). The reason for this - /// is that booleans automatically convert up to short, int, float, etc. - /// The result is that this: if(linkedPtr == 1) would yield true (bad). - typedef T* (this_type::*bool_)() const; - operator bool_() const - { - if(mpValue) - return &this_type::get; - return NULL; - } - - - /// operator! - /// This returns the opposite of operator bool; it returns true if - /// the owned pointer is null. Some compilers require this and some don't. - bool operator!() - { - return (mpValue == NULL); - } - - - /// detach - /// Returns ownership of the pointer to the caller. Fixes all - /// references to the pointer by any other owners to be NULL. - /// This function can work properly only if all entries in the list - /// refer to type T and none refer to any other type (e.g. U). - T* detach() - { - T* const pValue = mpValue; - - linked_ptr_base* p = this; - do - { - linked_ptr_base* const pNext = p->mpNext; - static_cast<this_type*>(p)->mpValue = NULL; - p->mpNext = p->mpPrev = p; - p = pNext; - } - while(p != this); - - return pValue; - } - - /// force_delete - /// Forces deletion of the shared pointer. Fixes all references to the - /// pointer by any other owners to be NULL. - /// This function can work properly only if all entries in the list - /// refer to type T and none refer to any other type (e.g. U). - void force_delete() - { - T* const pValue = detach(); - Deleter del; - del(pValue); - } - - }; // class linked_ptr - - - - /// get_pointer - /// Returns linked_ptr::get() via the input linked_ptr. Provided for compatibility - /// with certain well-known libraries that use this functionality. - template <typename T, typename D> - inline T* get_pointer(const linked_ptr<T, D>& linkedPtr) - { - return linkedPtr.get(); - } - - - /// operator== - /// Compares two linked_ptr objects for equality. Equality is defined as - /// being true when the pointer shared between two linked_ptr objects is equal. - template <typename T, typename TD, typename U, typename UD> - inline bool operator==(const linked_ptr<T, TD>& linkedPtr1, const linked_ptr<U, UD>& linkedPtr2) - { - return (linkedPtr1.get() == linkedPtr2.get()); - } - - - /// operator!= - /// Compares two linked_ptr objects for inequality. Equality is defined as - /// being true when the pointer shared between two linked_ptr objects is equal. - template <typename T, typename TD, typename U, typename UD> - inline bool operator!=(const linked_ptr<T, TD>& linkedPtr1, const linked_ptr<U, UD>& linkedPtr2) - { - return (linkedPtr1.get() != linkedPtr2.get()); - } - - - /// operator< - /// Returns which linked_ptr is 'less' than the other. Useful when storing - /// sorted containers of linked_ptr objects. - template <typename T, typename TD, typename U, typename UD> - inline bool operator<(const linked_ptr<T, TD>& linkedPtr1, const linked_ptr<U, UD>& linkedPtr2) - { - return (linkedPtr1.get() < linkedPtr2.get()); - } - - -} // namespace eastl - - -#endif // Header include guard - - - - - - - - - - - - - - - - - - - - |