aboutsummaryrefslogtreecommitdiff
path: root/EASTL/include/EASTL/shared_array.h
diff options
context:
space:
mode:
Diffstat (limited to 'EASTL/include/EASTL/shared_array.h')
-rw-r--r--EASTL/include/EASTL/shared_array.h434
1 files changed, 434 insertions, 0 deletions
diff --git a/EASTL/include/EASTL/shared_array.h b/EASTL/include/EASTL/shared_array.h
new file mode 100644
index 0000000..b7d7840
--- /dev/null
+++ b/EASTL/include/EASTL/shared_array.h
@@ -0,0 +1,434 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright (c) Electronic Arts Inc. All rights reserved.
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Note (March 2014): shared_array is not a full implementation of an array version
+// of C++11 shared_ptr, and there currently are no plans to make it so. A future
+// version of shared_ptr would likely take on the ability to store arrays,
+// same as unique_ptr has array support. This class isn't deprecated, but it
+// is frozen until some future decision is made on what to do about arrays.
+//
+///////////////////////////////////////////////////////////////////////////////
+// This class implements a shared_array template. This is a class which is
+// similar to the C++ shared_ptr template, except that it works with arrays
+// instead of individual objects.
+//
+// Important notice:
+// As of this writing (9/2003), the implementation provided here has
+// limitations that you should be aware of. These limitations will be shortly
+// rectified. Most significantly, this implementation has the following
+// weaknesses:
+// - It cannot safely deal with exceptions that occur during the
+// construction of shared_ptr objects.
+// - It cannot safely deal with recursive shared_ptr objects.
+// If a shared_ptr<A> holds a pointer to an instance of A and
+// class A owns an instance of shared_ptr<A> that refers to,
+// the original instance, the memory will leak.
+// - A template of type shared_ptr<void> will not call the destructor
+// for an object that it stores. You thus must declare a shared_ptr
+// template specifically for the class type.
+// - It doesn't safely handle multiple instances of shared_ptr
+// which own the same pointer accessed from multiple threads.
+// This weakness is by design, for performance reasons. You should
+// use shared_ptr_mt for multi-thread safe access.
+//
+// The rectification of the above issues are discussed in the C++ standardization
+// documents for the next C++ standard (as of 2003):
+// http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1450.html#Implementation-difficulty
+//
+// This current implementation will be eventually (hopefully by 1/2004) rectified
+// to be in line with the second generation C++ standard proposal.
+//
+// The intended design of this class is based somewhat on the design of the Boost
+// shared_array template. This design is also being considered for the next C++
+// standard (as of 2003). The C++ standard update proposal is currently available at:
+// http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1450.html
+// Boost smart pointers, including shared_array are documented at:
+// http://www.boost.org/libs/smart_ptr/
+//
+// As of this writing (10/2003), this class has received approval from EA legal
+// for use. The potential issue is the similarity of the class name and class
+// interface to existing open source code.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef EASTL_SHARED_ARRAY_H
+#define EASTL_SHARED_ARRAY_H
+
+
+#include <EASTL/internal/config.h>
+#include <EASTL/internal/smart_ptr.h> // Defines smart_array_deleter
+
+
+EA_DISABLE_ALL_VC_WARNINGS();
+
+ #include <new>
+ #include <stddef.h>
+
+EA_RESTORE_ALL_VC_WARNINGS();
+
+#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
+{
+
+ /// EASTL_SHARED_ARRAY_DEFAULT_NAME
+ ///
+ /// Defines a default container name in the absence of a user-provided name.
+ ///
+ #ifndef EASTL_SHARED_ARRAY_DEFAULT_NAME
+ #define EASTL_SHARED_ARRAY_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX " shared_array" // Unless the user overrides something, this is "EASTL shared_array".
+ #endif
+
+
+ /// EASTL_SHARED_ARRAY_DEFAULT_ALLOCATOR
+ ///
+ #ifndef EASTL_SHARED_ARRAY_DEFAULT_ALLOCATOR
+ #define EASTL_SHARED_ARRAY_DEFAULT_ALLOCATOR allocator_type(EASTL_SHARED_ARRAY_DEFAULT_NAME)
+ #endif
+
+
+
+ /// class shared_array
+ /// A shared_array is the same as shared_ptr but for arrays.
+ template <typename T, typename Allocator = EASTLAllocatorType, typename Deleter = smart_array_deleter<T> >
+ class shared_array
+ {
+ protected:
+ /// this_type
+ /// This is an alias for shared_array<T>, this class.
+ typedef shared_array<T> this_type;
+
+ /// allocator_type
+ typedef Allocator allocator_type;
+
+ /// deleter_type
+ typedef Deleter deleter_type;
+
+ /// ref_count
+ /// An internal reference count type. Must be convertable to int
+ /// so that the public use_count function can work.
+ typedef int ref_count;
+
+ T* mpArray; /// The owned pointer. Points to an array of T.
+ ref_count* mpRefCount; /// Reference count for owned pointer.
+ allocator_type mAllocator; /// The allocator used to manage new/delete of mpRefCount.
+
+ public:
+ typedef T element_type;
+
+ /// shared_array
+ /// Takes ownership of the pointer and sets the reference count
+ /// to the pointer to 1. It is OK if the input pointer is null.
+ /// The shared reference count is allocated on the heap via operator new.
+ /// If an exception occurs during the allocation of the shared
+ /// reference count, the owned pointer is deleted and the exception
+ /// is rethrown. A null pointer is given a reference count of 1.
+ explicit shared_array(T* pArray = NULL, const allocator_type& allocator = EASTL_SHARED_ARRAY_DEFAULT_ALLOCATOR)
+ : mpArray(pArray),
+ mpRefCount(NULL),
+ mAllocator(allocator)
+ {
+ // Allocate memory for the reference count.
+ void* const pMemory = EASTLAlloc(mAllocator, sizeof(ref_count));
+ if(pMemory)
+ mpRefCount = ::new(pMemory) ref_count(1);
+ }
+
+
+ /// shared_array
+ /// Shares ownership of a pointer with another instance of shared_array.
+ /// This function increments the shared reference count on the pointer.
+ /// If we want a shared_array constructor that is templated on shared_array<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.
+ shared_array(const shared_array& sharedArray)
+ : mpArray(sharedArray.mpArray),
+ mpRefCount(sharedArray.mpRefCount),
+ mAllocator(sharedArray.mAllocator)
+ {
+ ++*mpRefCount;
+ }
+
+
+ /// ~shared_array
+ /// Decrements the reference count for the owned pointer. If the
+ /// reference count goes to zero, the owned pointer is deleted and
+ /// the shared reference count is deleted.
+ ~shared_array()
+ {
+ const ref_count newRefCount(--*mpRefCount);
+ // assert(newRefCount >= 0);
+ if(newRefCount == 0)
+ {
+ EASTLFree(mAllocator, mpRefCount, sizeof(ref_count));
+ Deleter del;
+ del(mpArray);
+ }
+ }
+
+
+ /// operator=
+ /// Copies another shared_array 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 releases the old pointer, decrementing its reference
+ /// count and deleting it if zero, takes shared ownership of the new
+ /// pointer and increments its reference count.
+ /// If we want a shared_array operator= that is templated on shared_array<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.
+ shared_array& operator=(const shared_array& sharedArray)
+ {
+ if(mpArray != sharedArray.mpArray)
+ {
+ // The easiest thing to do is to create a temporary and
+ // copy ourselves ourselves into it. This is a standard
+ // method for switching pointer ownership in systems like this.
+ shared_array(sharedArray).swap(*this);
+ }
+ return *this;
+ }
+
+
+ /// operator=
+ /// Assigns a new pointer, while decrementing the reference count on
+ /// the current pointer. The new pointer can be NULL and the current
+ /// pointer can NULL. If the new pointer is equivalent to the current
+ /// pointer, then nothing is done.
+ shared_array& operator=(T* 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.
+ void reset(T* pArray = NULL)
+ {
+ if(pArray != mpArray)
+ {
+ // The easiest thing to do is to create a temporary and
+ // copy ourselves ourselves into it. This is a standard
+ // method for switching pointer ownership in systems like this.
+ shared_array(pArray, mAllocator).swap(*this);
+ }
+ }
+
+
+ /// swap
+ /// Exchanges the owned pointer beween two shared_array objects.
+ void swap(this_type& sharedArray)
+ {
+ // We leave mAllocator as-is.
+
+ // eastl::swap(mpArray, sharedArray.mpArray);
+ T* const pArray = sharedArray.mpArray;
+ sharedArray.mpArray = mpArray;
+ mpArray = pArray;
+
+ // eastl::swap(mpRefCount, sharedArray.mpRefCount);
+ ref_count* const pRefCount = sharedArray.mpRefCount;
+ sharedArray.mpRefCount = mpRefCount;
+ mpRefCount = pRefCount;
+ }
+
+
+ /// operator[]
+ /// Returns a reference to the specified item in the owned pointer
+ /// array.
+ /// Example usage:
+ /// shared_array<int> ptr = new int[6];
+ /// int x = ptr[2];
+ T& operator[](ptrdiff_t i) const
+ {
+ // assert(mpArray && (i >= 0));
+ return mpArray[i];
+ }
+
+ /// operator*
+ /// Returns the owner pointer dereferenced.
+ /// Example usage:
+ /// shared_array<int> ptr = new int(3);
+ /// int x = *ptr;
+ T& operator*() const
+ {
+ // assert(mpArray);
+ return *mpArray;
+ }
+
+ /// operator->
+ /// Allows access to the owned pointer via operator->()
+ /// Example usage:
+ /// struct X{ void DoSomething(); };
+ /// shared_array<int> ptr = new X;
+ /// ptr->DoSomething();
+ T* operator->() const EA_NOEXCEPT
+ {
+ // assert(mpArray);
+ return mpArray;
+ }
+
+ /// 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.
+ /// Example usage:
+ /// struct X{ void DoSomething(); };
+ /// shared_array<int> ptr = new X;
+ /// X* pX = ptr.get();
+ /// pX->DoSomething();
+ T* get() const EA_NOEXCEPT
+ {
+ return mpArray;
+ }
+
+ /// use_count
+ /// Returns the reference count on the owned pointer.
+ /// The return value is one if the owned pointer is null.
+ int use_count() const
+ {
+ // assert(mpRefCount);
+ return (int)*mpRefCount;
+ }
+
+ /// unique
+ /// Returns true if the reference count on the owned pointer is one.
+ /// The return value is true if the owned pointer is null.
+ bool unique() const
+ {
+ // assert(mpRefCount);
+ return (*mpRefCount == 1);
+ }
+
+ /// Implicit operator bool
+ /// Allows for using a scoped_ptr as a boolean.
+ /// Example usage:
+ /// shared_array<int> ptr = new int(3);
+ /// if(ptr)
+ /// ++*ptr;
+ ///
+ /// 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(sharedArray == 1) would yield true (bad).
+ typedef T* (this_type::*bool_)() const;
+ operator bool_() const EA_NOEXCEPT
+ {
+ if(mpArray)
+ 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.
+ /// shared_array<int> ptr = new int(3);
+ /// if(!ptr)
+ /// assert(false);
+ bool operator!() const EA_NOEXCEPT
+ {
+ return (mpArray == NULL);
+ }
+
+ /// get_allocator
+ /// Returns the memory allocator associated with this class.
+ const allocator_type& get_allocator() const EA_NOEXCEPT
+ {
+ return mAllocator;
+ }
+ allocator_type& get_allocator() EA_NOEXCEPT
+ {
+ return mAllocator;
+ }
+
+ /// set_allocator
+ /// Sets the memory allocator associated with this class.
+ void set_allocator(const allocator_type& allocator)
+ {
+ mAllocator = allocator;
+ }
+
+ }; // class shared_array
+
+
+
+ /// get_pointer
+ /// returns shared_array::get() via the input shared_array.
+ template <typename T, typename A, typename D>
+ inline T* get_pointer(const shared_array<T, A, D>& sharedArray)
+ {
+ return sharedArray.get();
+ }
+
+ /// swap
+ /// Exchanges the owned pointer beween two shared_array objects.
+ /// This non-member version is useful for compatibility of shared_array
+ /// objects with the C++ Standard Library and other libraries.
+ template <typename T, typename A, typename D>
+ inline void swap(shared_array<T, A, D>& sharedArray1, shared_array<T, A, D>& sharedArray2)
+ {
+ sharedArray1.swap(sharedArray2);
+ }
+
+
+ /// operator!=
+ /// Compares two shared_array objects for equality. Equality is defined as
+ /// being true when the pointer shared between two shared_array objects is equal.
+ /// It is debatable what the appropriate definition of equality is between two
+ /// shared_array objects, but we follow the current 2nd generation C++ standard proposal.
+ template <typename T, typename TA, typename TD, typename U, typename UA, typename UD>
+ inline bool operator==(const shared_array<T, TA, TD>& sharedArray1, const shared_array<U, UA, UD>& sharedArray2)
+ {
+ // assert((sharedArray1.get() != sharedArray2.get()) || (sharedArray1.use_count() == sharedArray2.use_count()));
+ return (sharedArray1.get() == sharedArray2.get());
+ }
+
+
+ /// operator!=
+ /// Compares two shared_array objects for inequality. Equality is defined as
+ /// being true when the pointer shared between two shared_array objects is equal.
+ /// It is debatable what the appropriate definition of equality is between two
+ /// shared_array objects, but we follow the current 2nd generation C++ standard proposal.
+ template <typename T, typename TA, typename TD, typename U, typename UA, typename UD>
+ inline bool operator!=(const shared_array<T, TA, TD>& sharedArray1, const shared_array<U, UA, UD>& sharedArray2)
+ {
+ // assert((sharedArray1.get() != sharedArray2.get()) || (sharedArray1.use_count() == sharedArray2.use_count()));
+ return (sharedArray1.get() != sharedArray2.get());
+ }
+
+
+ /// operator<
+ /// Returns which shared_array is 'less' than the other. Useful when storing
+ /// sorted containers of scoped_ptr objects.
+ template <typename T, typename TA, typename TD, typename U, typename UA, typename UD>
+ inline bool operator<(const shared_array<T, TA, TD>& sharedArray1, const shared_array<U, UA, UD>& sharedArray2)
+ {
+ return (sharedArray1.get() < sharedArray2.get()); // Alternatively use: std::less<T*>(a.get(), b.get());
+ }
+
+
+} // namespace eastl
+
+
+#endif // Header include guard
+
+
+
+
+
+
+
+
+
+
+