Click here to Skip to main content
15,879,326 members
Articles / Programming Languages / C++

Smart pointers for single owners and their aliases

Rate me:
Please Sign up or sign in to vote.
4.82/5 (12 votes)
14 Apr 2014CPOL28 min read 37K   377   56  
The missing link for complete memory and pointer safety in C++
//#include "ptr_engine0.h" //No class slicing protection 
						   //Relies on comprehensive correct use of virtual destructors
							//pointers 2 to 3 times larger
	
	//#define XNR_VIRTUAL_DESTRUCTOR_WARNINGS



namespace xnr {


	class _null_ptr;
		
	namespace eng {

	class _has_ref_counts
	{
	private:
	
	public:
		
		_DGNSTC_DECLARE_RC_COUNTER

	protected:

		class reference_controler;/*Forward Declaration*/

		_has_ref_counts() : m_pRC(NULL) {}

		class reference_controler
		{
		public:
	#ifdef XNR_MEMORY_POOL
			static xnr_memory_pool<reference_controler> stm_RefControlerPool;
			_DGNSTC_MEMORY_POOL_MONITOR0

			void *operator new(size_t  size)
				{return stm_RefControlerPool.give_new_slot();}

			void operator delete (void *p)
				{stm_RefControlerPool.take_back_slot(p);}
	#endif
		protected:
			LONG m_WeakCount;
			LONG m_StrongCount;
		public:		
			reference_controler() : m_WeakCount(1), m_StrongCount(1){_DGNSTC_INC_RC_COUNT}
			~reference_controler(){_DGNSTC_DEC_RC_COUNT}

		
			inline void AddWeakRef() {m_WeakCount++;}
			bool ReleaseWeak()
			{
				if(0==--m_WeakCount)
				{
					delete this;
					return true;
				}
				else
					return false;
			}
			void AddStrongRef()
			{
				if(m_StrongCount<0)
					m_StrongCount--;
				else
					m_StrongCount++;
				
			}
			inline bool IsValidObject()	{return (m_StrongCount!=0);	}
			bool ReleaseStrong()//Decrements strong count
			{					//returns true if object must be deleted
				
				if(m_StrongCount<0)
				{
					if(0==++m_StrongCount)
						xnr_fatal_error("Deletion while used by Fast Pointer");
					return false;
				}
				if(0==--m_StrongCount)
				{
					return true;
				}
				else
					return false;
			}

			bool ResetStrong()	//Resets strong count
			{					//returns true if object must be deleted
				
				if(m_StrongCount<0)
				#ifdef FOR_RELEASE
					m_StrongCount=-1;
				#else
					xnr_fatal_error("Deletion while used by Fast Pointer");
				#endif
				else
				{
					m_StrongCount=0;
					return true;
				}
				return false;
			}

			void QuietResetStrong() //Resets strong count
			{						//Does not indicate deletion of object
				
				if(m_StrongCount<0)
					xnr_fatal_error("Deletion while used by Fast Pointer");
				m_StrongCount=0;
			}

			reference_controler* CloneAndReset()
			{
				if(m_StrongCount<0)
				#ifdef FOR_RELEASE
					m_StrongCount=-1;
				#else
					xnr_fatal_error("Deletion while used by Fast Pointer");
				#endif

				return new reference_controler;
			}

			bool FastPtrLock()
			{
				if(m_StrongCount>0)
				{
					m_StrongCount=-m_StrongCount;
					#ifdef FOR_RELEASE
						m_StrongCount--;
					#endif
					return true;
				}
				else
					return false;
			
			}
			void FastPtrUnlock()
			{
				if(m_StrongCount<0)
				{
					m_StrongCount=-m_StrongCount;
					#ifdef FOR_RELEASE
						m_StrongCount--;
					#endif
				}
			
			}
				
		};
		
		template <class U>	reference_controler* _assure_reference_controler(U* pT) const
		{
			if(NULL==m_pRC)
				m_pRC=new reference_controler;
			return m_pRC;
		}

		void _quiet_hard_reset()
		{
			if(m_pRC!=NULL)
			{
				m_pRC->QuietResetStrong();

				//ReleaseWeak() deletes reference controller when weak_count==0 
				m_pRC->ReleaseWeak();
				m_pRC=NULL;
			}
		}
		
		mutable reference_controler* m_pRC;

	};

	template <class U> class _ptr;


	template <class T> class _ptr : protected _has_ref_counts
	{
		friend class _has_ref_counts;
		template <class U> friend class _value_with_counts;
		template <class U>	friend class _ptr;

	private:
		
		mutable T* m_pT;


	protected:
		_ptr() : m_pT(NULL) {}

		inline T* get_unchecked_pointer()const {return (T*)(this->m_pT);}
		

		inline void _throw_if_invalid() const
		{
			if(false==_is_valid())
				xnr_exception_error("NULL reference");
		}

		inline void _just_throw() const
		{
			xnr_exception_error("NULL reference");
		}

		inline void _throw_if_null() const
		{
			if(NULL==this->m_pT)
				xnr_exception_error("NULL _owner_ptr");
		}

		void _reset()
		{
			if(m_pRC!=NULL)
			{
				if(m_pRC->ReleaseStrong())
					delete m_pT;//deletes object when strong_count==0
				m_pRC->ReleaseWeak();//deletes reference controller when weak_count==0 
				m_pRC=NULL;
			}
			else if(this->m_pT)
				delete this->m_pT;//no reference controler - just delete the object
			this->m_pT=NULL;
		}
		void _quiet_reset()
		{
			if(m_pRC!=NULL)
			{
				m_pRC->ReleaseStrong();
					//No delete
				m_pRC->ReleaseWeak();//deletes reference controller when weak_count==0 
				m_pRC=NULL;
			}
			//No delete
			this->m_pT=NULL;
		}

		void _hard_reset()
		{
			if(m_pRC!=NULL)
			{
				if(m_pRC->ResetStrong())
					delete m_pT;
				m_pRC->ReleaseWeak();//deletes reference controller when weak_count==0
				m_pRC=NULL;
			}
			else if(this->m_pT)
				delete this->m_pT;//no reference controler - just delete the object
			this->m_pT=NULL;
		}

		void _quiet_hard_reset()
		{
			_has_ref_counts::_quiet_hard_reset();
			this->m_pT=NULL;
		}

		void _release()const 
		{
			if(m_pRC!=NULL)
			{
				m_pRC->ReleaseWeak();//deletes reference controller when weak_count==0
				m_pRC=NULL;//and forget it
			}
			this->m_pT=NULL;
		}

		template <class U>	void _point_to_ref(_ptr<U> const& r)
		{
			if(r._is_valid())
			{
				this->m_pT=r.m_pT;
				m_pRC=r.m_pRC;
				m_pRC->AddWeakRef();
			}
		}
		template <class U>	void _point_to_owner(_ptr<U> const& apT)
		{		
			if(apT._is_valid())
			{
				this->m_pT=apT.m_pT;
				m_pRC=apT._assure_reference_controler<U>(apT.m_pT);
				m_pRC->AddWeakRef();
			}
		}
		template <class U>	void _point_to_p(U* const& p)
		{
			this->m_pT=p;
			m_pRC=NULL;
		}
		
		bool _fast_ptr_lock()
		{
			return m_pRC->FastPtrLock();
		}
		void _fast_ptr_unlock()
		{
			if(m_pRC)
				return m_pRC->FastPtrUnlock();
		}
		void _assign_from_raw(T*const pT)
		{
			this->m_pT=pT;
		}
		template <class U>	void _assign_from_raw(U*const pU) 
		{
			this->m_pT=pU; //_assure_reference_controler<U>(pU);
	#ifdef XNR_VIRTUAL_DESTRUCTOR_WARNINGS
			struct{};
			//*** WARNING  Base class owner; virtual destructor required **** //
			//*********** See Output window for classes affected  ************//
	#endif
		}

		void _adopt(_ptr<T> const& ope)
		{
			if(ope._is_valid())
			{
				this->m_pT = ope.m_pT;
				m_pRC = ope.m_pRC;
				ope.m_pRC = NULL;
				ope.m_pT = NULL;
			}
		}

		template <class U>	void _adopt(_ptr<U> const& ope)
		{
			if(ope._is_valid())
			{	
				this->m_pT = ope.m_pT;
				m_pRC =ope._assure_reference_controler<U>(ope.m_pT);//ope.m_pRC;
				ope.m_pRC = NULL;
				ope.m_pT = NULL;
			}
			#ifdef XNR_VIRTUAL_DESTRUCTOR_WARNINGS
				struct{};
				//*** WARNING  Base class owner; virtual destructor required **** //
				//*********** See Output window for classes affected  ************//
			#endif
		}
		
		void _steal(_ptr<T>const& apT)
		{
			if(apT._is_valid())
			{
				this->m_pT = apT.m_pT;
				if(apT.m_pRC)
				{
					m_pRC = apT.m_pRC->CloneAndReset();
					apT.m_pRC->ReleaseWeak();
					apT.m_pRC=NULL;
				}
				apT.m_pT = NULL;
			}
		}

		template <class U>	void _steal(_ptr<U>const& apT)
		{
			if(apT._is_valid())
			{
				this->m_pT = apT.m_pT;
				if(apT.m_pRC)
				{
					m_pRC = apT.m_pRC.CloneAndReset();
					apT.m_pRC.ReleaseWeak();
					apT.m_pRC=NULL;
				}
				else
					_assure_reference_controler<U>(apT.m_pT);
				apT.m_pT = NULL;
			}
		}
		template <class U>	void _share(_ptr<U> const& spT)
		{
			if(spT._is_valid())
			{
				this->m_pT=spT.m_pT;
				m_pRC=spT._assure_reference_controler<U>(spT.m_pT);
				m_pRC->AddWeakRef();
				m_pRC->AddStrongRef();
			}
		}

	#ifdef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED	
		void _hold_boost_shared_ptr(boost::shared_ptr<T>const& sh)
		{
			m_pRC=(reference_controler*)new boost::shared_ptr<T>(sh);
			m_pT=sh.get();
		}
		void _hold_boost_weak_ptr(boost::weak_ptr<T>const& wp)
		{
			m_pRC=(reference_controler*)new boost::shared_ptr<T>(wp);
			m_pT=((boost::shared_ptr<T>*)m_pRC)->get();
		}
		void _release_boost_ptr()
		{
			delete (boost::shared_ptr<T>*)m_pRC;
		}
	#endif
		
	public:
		bool _is_valid() const
		{
			if(
				(m_pRC!= NULL && m_pRC->IsValidObject())
				||
				(NULL==m_pRC && this->m_pT!=0)
				)
				return true;
			else
				_release();
			return false;
		}
		template <class U>	void _downcast_from(_ptr<U> const& apT)
		{		
			if(apT._is_valid())
			{
				this->m_pT=static_cast<T*>(apT.m_pT);
				m_pRC=apT._assure_reference_controler<U>(apT.m_pT);
				if(m_pRC)
					m_pRC->AddWeakRef();
			}
		}
		T* get_pointer() const {if(_is_valid()) return this->m_pT; return NULL;}

	//================================================================1=========//
	//			Public operations and prohibtions common to all pointers
	//==============================================================================//

		public: \
			bool operator!=(_null_ptr& wpT)const {return get_pointer()!=NULL;}\
			bool operator==(_null_ptr& wpT)const {return NULL==get_pointer();}\
			template<class U>	bool operator==(_ptr<U>const& wpT)const {return get_pointer()==static_cast<T*>(wpT.get_pointer());}\
			template<class U>	bool operator!=(_ptr<U>const& wpT)const {return get_pointer()!=static_cast<T*>(wpT.get_pointer());}\
			operator bool() const {	return _is_valid();}\
		private:\
			void*  operator new(unsigned int s)	{return NULL;}\
			operator void*() const 	{return NULL;}\
			const T** operator&() {return &(this->m_pT);}
		
	};

	template <class T> class _value_with_counts : protected _has_ref_counts
	{
	protected:
		_value_with_counts(){}

		~_value_with_counts(){_quiet_hard_reset();}
	public:
		
		void _set_ptr_to_value_with_counts(_ptr<T>& r, T* pT)
		{
			r.m_pRC=_has_ref_counts::_assure_reference_controler(pT);
			m_pRC->AddWeakRef();
			r.m_pT=pT;
		}
	};

	#ifdef _DGNSTC
	int ptr_engine_diagnostic();
	#endif

	}//namespace eng

	template <class T> class vtor : public T
	{
	public:
		virtual ~vtor()
		{

		}
	};
}//namespace xnr

#define XNR_MEMORY_POOL_INSTANCE xnr_memory_pool<eng::_has_ref_counts::reference_controler> eng::_has_ref_counts::reference_controler::stm_RefControlerPool(100);

#define xnr_virtual virtual

#define PTR_ENGINE_DEFINED

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Retired
Spain Spain
Software Author with engineering, science and mathematical background.

Many years using C++ to develop responsive visualisations of fine grained dynamic information largely in the fields of public transport and supply logistics. Currently interested in what can be done to make the use of C++ cleaner, safer, and more comfortable.

Comments and Discussions