<commit_before>#ifndef STINGRAYKIT_SHARED_PTR_H
#define STINGRAYKIT_SHARED_PTR_H

// Copyright (c) 2011 - 2015, GS Group, https://github.com/GSGroup
// Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted,
// provided that the above copyright notice and this permission notice appear in all copies.
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.


#include <stingraykit/CheckedDelete.h>
#include <stingraykit/Dummy.h>
#include <stingraykit/Macro.h>
#include <stingraykit/TypeErasure.h>
#include <stingraykit/TypeInfo.h>
#include <stingraykit/aligned_storage.h>
#include <stingraykit/assert.h>
#include <stingraykit/dynamic_caster.h>
#include <stingraykit/exception.h>
#include <stingraykit/fatal.h>
#include <stingraykit/safe_bool.h>
#include <stingraykit/toolkit.h>
#include <stingraykit/thread/atomic/AtomicInt.h>

#include <sys/types.h>

#include <stdexcept>

namespace stingray
{


#define STINGRAYKIT_DECLARE_PTR(ClassName) \
		typedef stingray::shared_ptr<ClassName>			ClassName##Ptr; \
		typedef stingray::weak_ptr<ClassName>			ClassName##WeakPtr

#define STINGRAYKIT_DECLARE_CONST_PTR(ClassName) \
		typedef stingray::shared_ptr<const ClassName>	ClassName##ConstPtr; \
		typedef stingray::weak_ptr<const ClassName>		ClassName##ConstWeakPtr


	template < typename T >
	struct shared_ptr_traits
	{
		static const bool trace_ref_counts = false;
		//static const char* get_trace_class_name();
	};


#define STINGRAYKIT_TRACE_SHARED_PTRS(ClassName_) \
		template < > struct shared_ptr_traits<ClassName_> \
		{ \
			static const bool trace_ref_counts = true; \
			static const char* get_trace_class_name() { return #ClassName_; }\
		}


	namespace Detail
	{
		struct ISharedPtrData : public TypeErasureBase
		{
			AtomicU32::Type _strongReferences;
			AtomicU32::Type _weakReferences;

			ISharedPtrData() : _strongReferences(1), _weakReferences(1)
			{ }
		};


		template<typename T>
		class DefaultSharedPtrData : public ISharedPtrData
		{
		private:
			T*	_ptr;

		public:
			DefaultSharedPtrData(T* ptr) : _ptr(ptr)
			{ }

			void Dispose()
			{ CheckedDelete(_ptr); }
		};


		template<typename T, typename Deleter>
		class DeleterSharedPtrData : public ISharedPtrData
		{
		private:
			T*		_ptr;
			Deleter	_deleter;

		public:
			DeleterSharedPtrData(T* ptr, const Deleter& deleter) : _ptr(ptr), _deleter(deleter)
			{ }

			void Dispose()
			{ _deleter(_ptr); }
		};


#define DETAIL_STINGRAYKIT_INPLACEDATA_CTOR(N_) \
	template<STINGRAYKIT_REPEAT(N_, STINGRAYKIT_TEMPLATE_PARAM_DECL, T)> \
	InplaceSharedPtrData(STINGRAYKIT_REPEAT(N_, STINGRAYKIT_FUNCTION_PARAM_DECL, T)) \
	{ _storage.Ctor(STINGRAYKIT_REPEAT(N_, STINGRAYKIT_FUNCTION_PARAM_USAGE, ~)); }


		template<typename T>
		class InplaceSharedPtrData : public ISharedPtrData
		{
		private:
			StorageFor<T>	_storage;

		public:
			InplaceSharedPtrData()
			{ _storage.Ctor(); }

			DETAIL_STINGRAYKIT_INPLACEDATA_CTOR(1)
			DETAIL_STINGRAYKIT_INPLACEDATA_CTOR(2)
			DETAIL_STINGRAYKIT_INPLACEDATA_CTOR(3)
			DETAIL_STINGRAYKIT_INPLACEDATA_CTOR(4)
			DETAIL_STINGRAYKIT_INPLACEDATA_CTOR(5)
			DETAIL_STINGRAYKIT_INPLACEDATA_CTOR(6)
			DETAIL_STINGRAYKIT_INPLACEDATA_CTOR(7)
			DETAIL_STINGRAYKIT_INPLACEDATA_CTOR(8)
			DETAIL_STINGRAYKIT_INPLACEDATA_CTOR(9)
			DETAIL_STINGRAYKIT_INPLACEDATA_CTOR(10)

			void Dispose()
			{ _storage.Dtor(); }

			T* Get()
			{ return &_storage.Ref(); }
		};


#undef DETAIL_STINGRAYKIT_INPLACEDATA_CTOR


		struct DisposeConcept : public function_info<void, TypeList_0>
		{
			template<typename T>
			static void Apply(T& t)
			{ t.Dispose(); }
		};


#define DETAIL_STINGRAYKIT_SHAREDPTRIMPL_ALLOCATE(N_) \
		template<typename DataImpl_, STINGRAYKIT_REPEAT(N_, STINGRAYKIT_TEMPLATE_PARAM_DECL, T)> \
		DataImpl_* Allocate(STINGRAYKIT_REPEAT(N_, STINGRAYKIT_FUNCTION_PARAM_DECL, T)) \
		{ return _value.Allocate<DataImpl_>(STINGRAYKIT_REPEAT(N_, STINGRAYKIT_FUNCTION_PARAM_USAGE, ~)); }


		class SharedPtrImpl
		{
			TypeErasure<TypeList<DisposeConcept>::type, ISharedPtrData>	_value;

		public:
			inline SharedPtrImpl()
			{ }

			template<typename DataImpl_>
			DataImpl_* Allocate()
			{ return _value.Allocate<DataImpl_>(); }

			DETAIL_STINGRAYKIT_SHAREDPTRIMPL_ALLOCATE(1)
			DETAIL_STINGRAYKIT_SHAREDPTRIMPL_ALLOCATE(2)
			DETAIL_STINGRAYKIT_SHAREDPTRIMPL_ALLOCATE(3)
			DETAIL_STINGRAYKIT_SHAREDPTRIMPL_ALLOCATE(4)
			DETAIL_STINGRAYKIT_SHAREDPTRIMPL_ALLOCATE(5)
			DETAIL_STINGRAYKIT_SHAREDPTRIMPL_ALLOCATE(6)
			DETAIL_STINGRAYKIT_SHAREDPTRIMPL_ALLOCATE(7)
			DETAIL_STINGRAYKIT_SHAREDPTRIMPL_ALLOCATE(8)
			DETAIL_STINGRAYKIT_SHAREDPTRIMPL_ALLOCATE(9)
			DETAIL_STINGRAYKIT_SHAREDPTRIMPL_ALLOCATE(10)

			void AddWeakReference()
			{
				if (_value.Get())
					AtomicU32::Inc(_value.Get()->_weakReferences);
			}

			void ReleaseWeakReference()
			{
				if (!_value.Get())
					return;

				u32 result = AtomicU32::Dec(_value.Get()->_weakReferences);
				if (result == 0)
				{
					STINGRAYKIT_ANNOTATE_HAPPENS_AFTER(&_value.Get()->_weakReferences);
					STINGRAYKIT_ANNOTATE_RELEASE(&_value.Get()->_weakReferences);

					_value.Free();
				}
				else
					STINGRAYKIT_ANNOTATE_HAPPENS_BEFORE(&_value.Get()->_weakReferences);
			}

			u32 GetStrongReferences() const
			{ return _value.Get() ? AtomicU32::Load(_value.Get()->_strongReferences) : 0; }

			u32 AddStrongReference()
			{
				if (!_value.Get())
					return 0;
				return AtomicU32::Inc(_value.Get()->_strongReferences);
			}

			u32 ReleaseStrongReference()
			{
				if (!_value.Get())
					return 0;

				u32 result = AtomicU32::Dec(_value.Get()->_strongReferences);
				if (result == 0)
				{
					STINGRAYKIT_ANNOTATE_HAPPENS_AFTER(&_value.Get()->_strongReferences);
					STINGRAYKIT_ANNOTATE_RELEASE(&_value.Get()->_strongReferences);
					Dispose();
				}
				else
					STINGRAYKIT_ANNOTATE_HAPPENS_BEFORE(&_value.Get()->_strongReferences);

				return result;
			}

			bool ReleaseStrongIfUnique()
			{
				if (!_value.Get())
					return false;

				u32 c = AtomicU32::CompareAndExchange(_value.Get()->_strongReferences, 1, 0);
				if (c != 1)
					return false;

				STINGRAYKIT_ANNOTATE_HAPPENS_AFTER(&_value.Get()->_strongReferences);
				STINGRAYKIT_ANNOTATE_RELEASE(&_value.Get()->_strongReferences);
				Dispose();
				return true;
			}

			u32 TryAddStrongReference()
			{
				if (!_value.Get())
					return 0;

				u32 c = AtomicU32::Load(_value.Get()->_strongReferences);
				while (c != 0)
				{
					u32 newc = AtomicU32::CompareAndExchange(_value.Get()->_strongReferences, c, c + 1);
					if (newc == c)
						return newc;
					c = newc;
				}
				return 0;
			}

			bool Before(const SharedPtrImpl& other) const
			{ return _value.Get() < other._value.Get(); }

		private:
			void Dispose()
			{
				_value.Call<DisposeConcept>();
				ReleaseWeakReference();
			}
		};

#undef DETAIL_STINGRAYKIT_SHAREDPTRIMPL_ALLOCATE

		void DoLogAddRef(const char* className, u32 refs, const void* objPtrVal, const void* sharedPtrPtrVal);
		void DoLogReleaseRef(const char* className, u32 refs, const void* objPtrVal, const void* sharedPtrPtrVal);


		template < typename T, bool DoTrace = shared_ptr_traits<T>::trace_ref_counts >
		struct SharedPtrRefCounter
		{
			static void LogAddRef(u32 referencesCount, const void* objPtrVal, const void* sharedPtrPtrVal)		{ }
			static void LogReleaseRef(u32 referencesCount, const void* objPtrVal, const void* sharedPtrPtrVal)	{ }
		};

		template < typename T >
		struct SharedPtrRefCounter<T, true>
		{
			static void LogAddRef(u32 referencesCount, const void* objPtrVal, const void* sharedPtrPtrVal)
			{ Detail::DoLogAddRef(shared_ptr_traits<T>::get_trace_class_name(), referencesCount, objPtrVal, sharedPtrPtrVal); }

			static void LogReleaseRef(u32 referencesCount, const void* objPtrVal, const void* sharedPtrPtrVal)
			{ Detail::DoLogReleaseRef(shared_ptr_traits<T>::get_trace_class_name(), referencesCount, objPtrVal, sharedPtrPtrVal); }
		};
	}


	template < typename T >
	class weak_ptr;


	template < typename T >
	struct MakeShared;


	/** @brief Simple shared_ptr implementation */
	template < typename T >
	class shared_ptr : public safe_bool<shared_ptr<T> >
	{
		template < typename U >
		friend class weak_ptr;

		template < typename U >
		friend class shared_ptr;

		template < typename U >
		friend struct MakeShared;

	private:
		T*						_rawPtr;
		Detail::SharedPtrImpl	_impl;

	private:
		inline shared_ptr(T* rawPtr, const Detail::SharedPtrImpl& impl) :
			_rawPtr(rawPtr), _impl(impl)
		{ }

	public:
		typedef T ValueType;


		explicit inline shared_ptr(T* rawPtr) : _rawPtr(rawPtr)
		{
			if (!_rawPtr)
				return;

			_impl.Allocate<Detail::DefaultSharedPtrData<T> >(rawPtr);
			LogAddRef(1);

			init_enable_shared_from_this(_rawPtr);
		}


		template<typename Deleter>
		inline shared_ptr(T* rawPtr, const Deleter& deleter) : _rawPtr(rawPtr)
		{
			_impl.Allocate<Detail::DeleterSharedPtrData<T, Deleter> >(rawPtr, deleter);
			LogAddRef(1);

			init_enable_shared_from_this(_rawPtr);
		}


		inline shared_ptr() : _rawPtr()
		{ }


		inline shared_ptr(const NullPtrType&) : _rawPtr()
		{ }


		inline shared_ptr(const shared_ptr<T>& other) :
			_rawPtr(other._rawPtr), _impl(other._impl)
		{ LogAddRef(_impl.AddStrongReference()); }


		template < typename U >
		inline shared_ptr(const shared_ptr<U>& other, typename EnableIf<Inherits<U, T>::Value, Dummy>::ValueT* = 0) :
			_rawPtr(other._rawPtr), _impl(other._impl)
		{ LogAddRef(_impl.AddStrongReference()); }


		/// @brief: Aliasing constuctor - similar to standard one
		template < typename U >
		inline shared_ptr(const shared_ptr<U>& other, T* ptr) :
			_rawPtr(ptr), _impl(other._impl)
		{ LogAddRef(_impl.AddStrongReference()); }


		inline ~shared_ptr()
		{ LogReleaseRef(_impl.ReleaseStrongReference()); }


		inline shared_ptr& operator = (const shared_ptr& other)
		{
			shared_ptr tmp(other);
			swap(tmp);

			// Uncomment this for tracing shared_ptrs
			//if (other == *this)
				//return *this;

			//this->~shared_ptr();
			//new(this) shared_ptr(other);

			return *this;
		}


		inline bool operator == (const T* ptr) const				{ return _rawPtr == ptr; }
		inline bool operator != (const T* ptr) const				{ return !(*this == ptr); }
		inline bool operator == (const shared_ptr& other) const		{ return _rawPtr == other._rawPtr; }
		inline bool operator != (const shared_ptr& other) const		{ return !(*this == other); }

		inline bool is_initialized() const							{ return _rawPtr != 0; }
		inline bool boolean_test() const							{ return is_initialized(); }

		inline weak_ptr<T> weak() const								{ return weak_ptr<T>(*this); }


		inline bool release_if_unique()
		{
			bool result = _impl.ReleaseStrongIfUnique();
			if (!result)
				return false;

			LogReleaseRef(0);
			_rawPtr = null;
			_impl = Detail::SharedPtrImpl();
			return true;
		}


		inline bool unique() const
		{ return use_count() == 1; }


		inline size_t use_count() const
		{ return _impl.GetStrongReferences(); }


		inline void reset(T* ptr = 0)
		{
			shared_ptr<T> tmp(ptr);
			swap(tmp);

			// Uncomment this for tracing shared_ptrs
			//this->~shared_ptr();
			//new(this) shared_ptr(ptr);
		}


		inline void swap(shared_ptr<T>& other)
		{
			std::swap(_rawPtr, other._rawPtr);
			std::swap(_impl, other._impl);
		}


		inline T* get() const			{ return _rawPtr; }
		inline T* operator -> () const	{ check_ptr(); return _rawPtr; }
		inline T& operator * () const	{ check_ptr(); return *_rawPtr; }


		template<typename U> bool owner_before(shared_ptr<U> const& other) const
		{ return _impl.Before(other._impl); }


		template<typename U> bool owner_before(weak_ptr<U> const& other) const
		{ return _impl.Before(other._impl); }

	private:
		inline void init_enable_shared_from_this(...) const
		{ }


		void LogAddRef(u32 referencesCount)
		{
			if (_rawPtr)
				Detail::SharedPtrRefCounter<T>::LogAddRef(referencesCount, _rawPtr, this);
		}


		void LogReleaseRef(u32 referencesCount)
		{
			if (_rawPtr)
				Detail::SharedPtrRefCounter<T>::LogReleaseRef(referencesCount, _rawPtr, this);
		}


		inline void check_ptr() const
		{ STINGRAYKIT_CHECK(_rawPtr, NullPointerException("shared_ptr<" + TypeInfo(typeid(T)).GetName() + ">")); }
	};


	template<typename T>
	void swap(shared_ptr<T>& lhs, shared_ptr<T>& rhs)
	{ lhs.swap(rhs); }



	/** @brief Simple weak_ptr implementation */
	template < typename T >
	class weak_ptr
	{
		template <typename U> friend class weak_ptr;
		template <typename U> friend class shared_ptr;

	private:
		T*								_rawPtr;
		mutable Detail::SharedPtrImpl	_impl;

	public:
		inline weak_ptr() : _rawPtr()
		{ }

		inline weak_ptr(const NullPtrType&) : _rawPtr()
		{ }

		inline weak_ptr(const shared_ptr<T>& sharedPtr) :
			_rawPtr(sharedPtr._rawPtr), _impl(sharedPtr._impl)
		{ _impl.AddWeakReference(); }

		template < typename U >
		inline weak_ptr(const shared_ptr<U>& sharedPtr) :
			_rawPtr(sharedPtr._rawPtr), _impl(sharedPtr._impl)
		{ _impl.AddWeakReference(); }

		inline weak_ptr(const weak_ptr& other) :
			_rawPtr(other._rawPtr), _impl(other._impl)
		{ _impl.AddWeakReference(); }

		template < typename U >
		inline weak_ptr(const weak_ptr<U>& other) :
			_rawPtr(other._rawPtr), _impl(other._impl)
		{ _impl.AddWeakReference(); }

		inline ~weak_ptr()
		{ _impl.ReleaseWeakReference(); }

		inline weak_ptr& operator = (const weak_ptr& other)
		{
			weak_ptr tmp(other);
			swap(tmp);
			return *this;
		}

		inline shared_ptr<T> lock() const
		{
			u32 sc = _impl.TryAddStrongReference();
			if (sc == 0)
				return shared_ptr<T>();

			if (_rawPtr)
				Detail::SharedPtrRefCounter<T>::LogAddRef(sc, _rawPtr, this);

			shared_ptr<T> result(_rawPtr, _impl);
			return result;
		}

		inline void reset()
		{
			weak_ptr<T> tmp;
			swap(tmp);
		}

		inline void swap(weak_ptr<T>& other)
		{
			std::swap(_rawPtr, other._rawPtr);
			std::swap(_impl, other._impl);<commit_msg>weak_ptr: add assignment operator from shared_ptr<commit_after>#ifndef STINGRAYKIT_SHARED_PTR_H
#define STINGRAYKIT_SHARED_PTR_H

// Copyright (c) 2011 - 2015, GS Group, https://github.com/GSGroup
// Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted,
// provided that the above copyright notice and this permission notice appear in all copies.
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.


#include <stingraykit/CheckedDelete.h>
#include <stingraykit/Dummy.h>
#include <stingraykit/Macro.h>
#include <stingraykit/TypeErasure.h>
#include <stingraykit/TypeInfo.h>
#include <stingraykit/aligned_storage.h>
#include <stingraykit/assert.h>
#include <stingraykit/dynamic_caster.h>
#include <stingraykit/exception.h>
#include <stingraykit/fatal.h>
#include <stingraykit/safe_bool.h>
#include <stingraykit/toolkit.h>
#include <stingraykit/thread/atomic/AtomicInt.h>

#include <sys/types.h>

#include <stdexcept>

namespace stingray
{


#define STINGRAYKIT_DECLARE_PTR(ClassName) \
		typedef stingray::shared_ptr<ClassName>			ClassName##Ptr; \
		typedef stingray::weak_ptr<ClassName>			ClassName##WeakPtr

#define STINGRAYKIT_DECLARE_CONST_PTR(ClassName) \
		typedef stingray::shared_ptr<const ClassName>	ClassName##ConstPtr; \
		typedef stingray::weak_ptr<const ClassName>		ClassName##ConstWeakPtr


	template < typename T >
	struct shared_ptr_traits
	{
		static const bool trace_ref_counts = false;
		//static const char* get_trace_class_name();
	};


#define STINGRAYKIT_TRACE_SHARED_PTRS(ClassName_) \
		template < > struct shared_ptr_traits<ClassName_> \
		{ \
			static const bool trace_ref_counts = true; \
			static const char* get_trace_class_name() { return #ClassName_; }\
		}


	namespace Detail
	{
		struct ISharedPtrData : public TypeErasureBase
		{
			AtomicU32::Type _strongReferences;
			AtomicU32::Type _weakReferences;

			ISharedPtrData() : _strongReferences(1), _weakReferences(1)
			{ }
		};


		template<typename T>
		class DefaultSharedPtrData : public ISharedPtrData
		{
		private:
			T*	_ptr;

		public:
			DefaultSharedPtrData(T* ptr) : _ptr(ptr)
			{ }

			void Dispose()
			{ CheckedDelete(_ptr); }
		};


		template<typename T, typename Deleter>
		class DeleterSharedPtrData : public ISharedPtrData
		{
		private:
			T*		_ptr;
			Deleter	_deleter;

		public:
			DeleterSharedPtrData(T* ptr, const Deleter& deleter) : _ptr(ptr), _deleter(deleter)
			{ }

			void Dispose()
			{ _deleter(_ptr); }
		};


#define DETAIL_STINGRAYKIT_INPLACEDATA_CTOR(N_) \
	template<STINGRAYKIT_REPEAT(N_, STINGRAYKIT_TEMPLATE_PARAM_DECL, T)> \
	InplaceSharedPtrData(STINGRAYKIT_REPEAT(N_, STINGRAYKIT_FUNCTION_PARAM_DECL, T)) \
	{ _storage.Ctor(STINGRAYKIT_REPEAT(N_, STINGRAYKIT_FUNCTION_PARAM_USAGE, ~)); }


		template<typename T>
		class InplaceSharedPtrData : public ISharedPtrData
		{
		private:
			StorageFor<T>	_storage;

		public:
			InplaceSharedPtrData()
			{ _storage.Ctor(); }

			DETAIL_STINGRAYKIT_INPLACEDATA_CTOR(1)
			DETAIL_STINGRAYKIT_INPLACEDATA_CTOR(2)
			DETAIL_STINGRAYKIT_INPLACEDATA_CTOR(3)
			DETAIL_STINGRAYKIT_INPLACEDATA_CTOR(4)
			DETAIL_STINGRAYKIT_INPLACEDATA_CTOR(5)
			DETAIL_STINGRAYKIT_INPLACEDATA_CTOR(6)
			DETAIL_STINGRAYKIT_INPLACEDATA_CTOR(7)
			DETAIL_STINGRAYKIT_INPLACEDATA_CTOR(8)
			DETAIL_STINGRAYKIT_INPLACEDATA_CTOR(9)
			DETAIL_STINGRAYKIT_INPLACEDATA_CTOR(10)

			void Dispose()
			{ _storage.Dtor(); }

			T* Get()
			{ return &_storage.Ref(); }
		};


#undef DETAIL_STINGRAYKIT_INPLACEDATA_CTOR


		struct DisposeConcept : public function_info<void, TypeList_0>
		{
			template<typename T>
			static void Apply(T& t)
			{ t.Dispose(); }
		};


#define DETAIL_STINGRAYKIT_SHAREDPTRIMPL_ALLOCATE(N_) \
		template<typename DataImpl_, STINGRAYKIT_REPEAT(N_, STINGRAYKIT_TEMPLATE_PARAM_DECL, T)> \
		DataImpl_* Allocate(STINGRAYKIT_REPEAT(N_, STINGRAYKIT_FUNCTION_PARAM_DECL, T)) \
		{ return _value.Allocate<DataImpl_>(STINGRAYKIT_REPEAT(N_, STINGRAYKIT_FUNCTION_PARAM_USAGE, ~)); }


		class SharedPtrImpl
		{
			TypeErasure<TypeList<DisposeConcept>::type, ISharedPtrData>	_value;

		public:
			inline SharedPtrImpl()
			{ }

			template<typename DataImpl_>
			DataImpl_* Allocate()
			{ return _value.Allocate<DataImpl_>(); }

			DETAIL_STINGRAYKIT_SHAREDPTRIMPL_ALLOCATE(1)
			DETAIL_STINGRAYKIT_SHAREDPTRIMPL_ALLOCATE(2)
			DETAIL_STINGRAYKIT_SHAREDPTRIMPL_ALLOCATE(3)
			DETAIL_STINGRAYKIT_SHAREDPTRIMPL_ALLOCATE(4)
			DETAIL_STINGRAYKIT_SHAREDPTRIMPL_ALLOCATE(5)
			DETAIL_STINGRAYKIT_SHAREDPTRIMPL_ALLOCATE(6)
			DETAIL_STINGRAYKIT_SHAREDPTRIMPL_ALLOCATE(7)
			DETAIL_STINGRAYKIT_SHAREDPTRIMPL_ALLOCATE(8)
			DETAIL_STINGRAYKIT_SHAREDPTRIMPL_ALLOCATE(9)
			DETAIL_STINGRAYKIT_SHAREDPTRIMPL_ALLOCATE(10)

			void AddWeakReference()
			{
				if (_value.Get())
					AtomicU32::Inc(_value.Get()->_weakReferences);
			}

			void ReleaseWeakReference()
			{
				if (!_value.Get())
					return;

				u32 result = AtomicU32::Dec(_value.Get()->_weakReferences);
				if (result == 0)
				{
					STINGRAYKIT_ANNOTATE_HAPPENS_AFTER(&_value.Get()->_weakReferences);
					STINGRAYKIT_ANNOTATE_RELEASE(&_value.Get()->_weakReferences);

					_value.Free();
				}
				else
					STINGRAYKIT_ANNOTATE_HAPPENS_BEFORE(&_value.Get()->_weakReferences);
			}

			u32 GetStrongReferences() const
			{ return _value.Get() ? AtomicU32::Load(_value.Get()->_strongReferences) : 0; }

			u32 AddStrongReference()
			{
				if (!_value.Get())
					return 0;
				return AtomicU32::Inc(_value.Get()->_strongReferences);
			}

			u32 ReleaseStrongReference()
			{
				if (!_value.Get())
					return 0;

				u32 result = AtomicU32::Dec(_value.Get()->_strongReferences);
				if (result == 0)
				{
					STINGRAYKIT_ANNOTATE_HAPPENS_AFTER(&_value.Get()->_strongReferences);
					STINGRAYKIT_ANNOTATE_RELEASE(&_value.Get()->_strongReferences);
					Dispose();
				}
				else
					STINGRAYKIT_ANNOTATE_HAPPENS_BEFORE(&_value.Get()->_strongReferences);

				return result;
			}

			bool ReleaseStrongIfUnique()
			{
				if (!_value.Get())
					return false;

				u32 c = AtomicU32::CompareAndExchange(_value.Get()->_strongReferences, 1, 0);
				if (c != 1)
					return false;

				STINGRAYKIT_ANNOTATE_HAPPENS_AFTER(&_value.Get()->_strongReferences);
				STINGRAYKIT_ANNOTATE_RELEASE(&_value.Get()->_strongReferences);
				Dispose();
				return true;
			}

			u32 TryAddStrongReference()
			{
				if (!_value.Get())
					return 0;

				u32 c = AtomicU32::Load(_value.Get()->_strongReferences);
				while (c != 0)
				{
					u32 newc = AtomicU32::CompareAndExchange(_value.Get()->_strongReferences, c, c + 1);
					if (newc == c)
						return newc;
					c = newc;
				}
				return 0;
			}

			bool Before(const SharedPtrImpl& other) const
			{ return _value.Get() < other._value.Get(); }

		private:
			void Dispose()
			{
				_value.Call<DisposeConcept>();
				ReleaseWeakReference();
			}
		};

#undef DETAIL_STINGRAYKIT_SHAREDPTRIMPL_ALLOCATE

		void DoLogAddRef(const char* className, u32 refs, const void* objPtrVal, const void* sharedPtrPtrVal);
		void DoLogReleaseRef(const char* className, u32 refs, const void* objPtrVal, const void* sharedPtrPtrVal);


		template < typename T, bool DoTrace = shared_ptr_traits<T>::trace_ref_counts >
		struct SharedPtrRefCounter
		{
			static void LogAddRef(u32 referencesCount, const void* objPtrVal, const void* sharedPtrPtrVal)		{ }
			static void LogReleaseRef(u32 referencesCount, const void* objPtrVal, const void* sharedPtrPtrVal)	{ }
		};

		template < typename T >
		struct SharedPtrRefCounter<T, true>
		{
			static void LogAddRef(u32 referencesCount, const void* objPtrVal, const void* sharedPtrPtrVal)
			{ Detail::DoLogAddRef(shared_ptr_traits<T>::get_trace_class_name(), referencesCount, objPtrVal, sharedPtrPtrVal); }

			static void LogReleaseRef(u32 referencesCount, const void* objPtrVal, const void* sharedPtrPtrVal)
			{ Detail::DoLogReleaseRef(shared_ptr_traits<T>::get_trace_class_name(), referencesCount, objPtrVal, sharedPtrPtrVal); }
		};
	}


	template < typename T >
	class weak_ptr;


	template < typename T >
	struct MakeShared;


	/** @brief Simple shared_ptr implementation */
	template < typename T >
	class shared_ptr : public safe_bool<shared_ptr<T> >
	{
		template < typename U >
		friend class weak_ptr;

		template < typename U >
		friend class shared_ptr;

		template < typename U >
		friend struct MakeShared;

	private:
		T*						_rawPtr;
		Detail::SharedPtrImpl	_impl;

	private:
		inline shared_ptr(T* rawPtr, const Detail::SharedPtrImpl& impl) :
			_rawPtr(rawPtr), _impl(impl)
		{ }

	public:
		typedef T ValueType;


		explicit inline shared_ptr(T* rawPtr) : _rawPtr(rawPtr)
		{
			if (!_rawPtr)
				return;

			_impl.Allocate<Detail::DefaultSharedPtrData<T> >(rawPtr);
			LogAddRef(1);

			init_enable_shared_from_this(_rawPtr);
		}


		template<typename Deleter>
		inline shared_ptr(T* rawPtr, const Deleter& deleter) : _rawPtr(rawPtr)
		{
			_impl.Allocate<Detail::DeleterSharedPtrData<T, Deleter> >(rawPtr, deleter);
			LogAddRef(1);

			init_enable_shared_from_this(_rawPtr);
		}


		inline shared_ptr() : _rawPtr()
		{ }


		inline shared_ptr(const NullPtrType&) : _rawPtr()
		{ }


		inline shared_ptr(const shared_ptr<T>& other) :
			_rawPtr(other._rawPtr), _impl(other._impl)
		{ LogAddRef(_impl.AddStrongReference()); }


		template < typename U >
		inline shared_ptr(const shared_ptr<U>& other, typename EnableIf<Inherits<U, T>::Value, Dummy>::ValueT* = 0) :
			_rawPtr(other._rawPtr), _impl(other._impl)
		{ LogAddRef(_impl.AddStrongReference()); }


		/// @brief: Aliasing constuctor - similar to standard one
		template < typename U >
		inline shared_ptr(const shared_ptr<U>& other, T* ptr) :
			_rawPtr(ptr), _impl(other._impl)
		{ LogAddRef(_impl.AddStrongReference()); }


		inline ~shared_ptr()
		{ LogReleaseRef(_impl.ReleaseStrongReference()); }


		inline shared_ptr& operator = (const shared_ptr& other)
		{
			shared_ptr tmp(other);
			swap(tmp);

			// Uncomment this for tracing shared_ptrs
			//if (other == *this)
				//return *this;

			//this->~shared_ptr();
			//new(this) shared_ptr(other);

			return *this;
		}


		inline bool operator == (const T* ptr) const				{ return _rawPtr == ptr; }
		inline bool operator != (const T* ptr) const				{ return !(*this == ptr); }
		inline bool operator == (const shared_ptr& other) const		{ return _rawPtr == other._rawPtr; }
		inline bool operator != (const shared_ptr& other) const		{ return !(*this == other); }

		inline bool is_initialized() const							{ return _rawPtr != 0; }
		inline bool boolean_test() const							{ return is_initialized(); }

		inline weak_ptr<T> weak() const								{ return weak_ptr<T>(*this); }


		inline bool release_if_unique()
		{
			bool result = _impl.ReleaseStrongIfUnique();
			if (!result)
				return false;

			LogReleaseRef(0);
			_rawPtr = null;
			_impl = Detail::SharedPtrImpl();
			return true;
		}


		inline bool unique() const
		{ return use_count() == 1; }


		inline size_t use_count() const
		{ return _impl.GetStrongReferences(); }


		inline void reset(T* ptr = 0)
		{
			shared_ptr<T> tmp(ptr);
			swap(tmp);

			// Uncomment this for tracing shared_ptrs
			//this->~shared_ptr();
			//new(this) shared_ptr(ptr);
		}


		inline void swap(shared_ptr<T>& other)
		{
			std::swap(_rawPtr, other._rawPtr);
			std::swap(_impl, other._impl);
		}


		inline T* get() const			{ return _rawPtr; }
		inline T* operator -> () const	{ check_ptr(); return _rawPtr; }
		inline T& operator * () const	{ check_ptr(); return *_rawPtr; }


		template<typename U> bool owner_before(shared_ptr<U> const& other) const
		{ return _impl.Before(other._impl); }


		template<typename U> bool owner_before(weak_ptr<U> const& other) const
		{ return _impl.Before(other._impl); }

	private:
		inline void init_enable_shared_from_this(...) const
		{ }


		void LogAddRef(u32 referencesCount)
		{
			if (_rawPtr)
				Detail::SharedPtrRefCounter<T>::LogAddRef(referencesCount, _rawPtr, this);
		}


		void LogReleaseRef(u32 referencesCount)
		{
			if (_rawPtr)
				Detail::SharedPtrRefCounter<T>::LogReleaseRef(referencesCount, _rawPtr, this);
		}


		inline void check_ptr() const
		{ STINGRAYKIT_CHECK(_rawPtr, NullPointerException("shared_ptr<" + TypeInfo(typeid(T)).GetName() + ">")); }
	};


	template<typename T>
	void swap(shared_ptr<T>& lhs, shared_ptr<T>& rhs)
	{ lhs.swap(rhs); }



	/** @brief Simple weak_ptr implementation */
	template < typename T >
	class weak_ptr
	{
		template <typename U> friend class weak_ptr;
		template <typename U> friend class shared_ptr;

	private:
		T*								_rawPtr;
		mutable Detail::SharedPtrImpl	_impl;

	public:
		inline weak_ptr() : _rawPtr()
		{ }

		inline weak_ptr(const NullPtrType&) : _rawPtr()
		{ }

		inline weak_ptr(const shared_ptr<T>& sharedPtr) :
			_rawPtr(sharedPtr._rawPtr), _impl(sharedPtr._impl)
		{ _impl.AddWeakReference(); }

		template < typename U >
		inline weak_ptr(const shared_ptr<U>& sharedPtr) :
			_rawPtr(sharedPtr._rawPtr), _impl(sharedPtr._impl)
		{ _impl.AddWeakReference(); }

		inline weak_ptr(const weak_ptr& other) :
			_rawPtr(other._rawPtr), _impl(other._impl)
		{ _impl.AddWeakReference(); }

		template < typename U >
		inline weak_ptr(const weak_ptr<U>& other) :
			_rawPtr(other._rawPtr), _impl(other._impl)
		{ _impl.AddWeakReference(); }

		inline ~weak_ptr()
		{ _impl.ReleaseWeakReference(); }

		inline weak_ptr& operator = (const weak_ptr& other)
		{
			weak_ptr tmp(other);
			swap(tmp);
			return *this;
		}

		template < typename U >
		inline weak_ptr& operator = (const shared_ptr<U>& other)
		{
			weak_ptr tmp(other);
			swap(tmp);
			return *this;
		}

		inline shared_ptr<T> lock() const
		{
			u32 sc = _impl.TryAddStrongReference();
			if (sc == 0)
				return shared_ptr<T>();

			if (_rawPtr)
				Detail::SharedPtrRefCounter<T>::LogAddRef(sc, _rawPtr, this);

			shared_ptr<T> result(_rawPtr, _impl);
			return result;
		}

		inline void reset()
		{
			weak_ptr<T> tmp;
			swap(tmp);
		}

		inline void swap(weak_ptr<T>& other)
		{
			std::swap(_rawPtr, other._rawPtr);
			std::swap(_impl, other._impl);
{'fraction_non_alphanumeric': 0.11488521865586372, 'fraction_numerical': 0.007548215089505211, 'mean_word_length': 4.331733431788813, 'pattern_counts': {'":': 0, '<': 187, '<?xml version=': 0, '>': 223, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5362396', 'n_tokens_mistral': 12114, 'n_tokens_neox': 10183, 'n_words': 2048}