text: #pragma once
  
  #include "ref_counted.h"
  
  #include <cgv/defines/assert.h>
  #include <cgv/type/cond/is_base_of.h>
  #include <cgv/type/cond/has_virtual_destructor.h>
  #include <assert.h>
  
  #include "lib_begin.h"
  
  namespace cgv {
  	/// namespace for data management components
  	namespace data {
  
  // extern CGV_API bool validate_delete(const void* ptr);
  
  template <class T, bool is_ref_counted>
  class ref_ptr;
  
  /// struct used to make ref pointers to ref_counted friends of ref_counted
  class ref_ptr_tag
  {
  protected:
  	/// increment the count of a ref counted object
  	void inc_ref_count(const ref_counted* ptr) const
  	{
  		ptr->set_ref_count(ptr->get_ref_count()+1);
  	}
  	/// decrement the count of a ref counted object and return whether to delete the object
  	bool dec_ref_count(const ref_counted* ptr) const
  	{
  		int count = ptr->get_ref_count();
  		if (count > 0) {
  			ptr->set_ref_count(count-1);
  			return count == 1;
  		}
  		// ERROR: zero ref count decremented
  		assert(0);
  		return false;
  	}
  };
  
  template <typename T, bool is_ref_counted = false>
  class ref_ptr_impl
  {
  protected:
  	friend class ref_ptr_impl<const T, is_ref_counted>;
  	/// struct to store the pointer with a count
  	struct counter_type 
  	{
  		counter_type(T* p, int c) : ptr(p), count(c) {}
  		T*  ptr;
  		int count;
  	};
  	/// store pointer to counter struct
  	mutable counter_type* counter;
  	/// decrement the count, delete if it is 0
  	void release()
  	{
  		if (counter) {
  			if (--counter->count == 0) {
  				delete counter->ptr;
  				counter->ptr = 0;
  				delete counter;
  			}
  			counter = 0;
  		}
  	}
  	/// return the pointer itself
  	T*	ref () const        { return counter ? counter->ptr : 0; }
  	/// construct reference counted pointer
  	explicit ref_ptr_impl(T* p = 0) : counter(0) {
  		if (p) 
  			counter = new counter_type(p, 1);
  	}
  	/// copy construct from same pointer type and increment count
  	ref_ptr_impl(const ref_ptr_impl<T,false>& r) : counter(r.counter)
  	{
  		if (counter)
  			++counter->count;
  	}
  	/// copy construct from pointer of derived type with virtual destructor
  	template <typename S>
  	ref_ptr_impl(const ref_ptr_impl<S,false>& s)
  	{
  		// ref_ptr conversion only valid if T is base of S
  		CGV_DEFINES_ASSERT(type::cond::is_base_of<T,S>::value);
  		// and T has a virtual destructor
  		CGV_DEFINES_ASSERT(type::cond::has_virtual_destructor<T>::value);
  		// after validity checks, set pointer 
  		counter = reinterpret_cast<counter_type*>(s.counter);
  		// and increment reference count
  		if (counter)
  			++counter->count;
  	}
  public:
  	/// return current count
  	int get_count() const  { return counter ? counter->count : 0; }
  };
  
  template <typename T>
  class ref_ptr_impl<T,true> : public ref_ptr_tag
  {
  	T* ptr;
  protected:
  	/// if the pointer had been initialized before, decrement reference count and release pointer, if necessary delete instance
  	void release() {
  		if (ptr) { 
  			if (dec_ref_count(ptr)) {
  //				if (validate_delete(ptr))
  					delete ptr;
  			}
  			ptr = 0; 
  		}
  	}
  	/// return the pointer itself
  	T*	ref () const         { 
  		return ptr; 
  	}
  	/// construct from pointer and increment reference count
  	explicit ref_ptr_impl(T* p) : ptr(p) {
  		if (ptr)
  			inc_ref_count(ptr);
  	}
  	/// copy construct from same pointer type and increment count
  	ref_ptr_impl(const ref_ptr_impl<T,true>& r) : ptr(r.ref())
  	{
  		if (ptr)
  			inc_ref_count(ptr);
  	}
  	/// copy construct from pointer of derived type with virtual destructor
  	template <typename S>
  	ref_ptr_impl(const ref_ptr_impl<S,true>& s)
  	{
  		// ref_ptr conversion only valid if T is base of S
  		CGV_DEFINES_ASSERT(type::cond::is_base_of<T,S>::value);
  		// and T has a virtual destructor
  		CGV_DEFINES_ASSERT(type::cond::has_virtual_destructor<T>::value);
  		// after validity checks, set pointer with a very bad hack!!
  		ptr = static_cast<const ref_ptr<S,true>&>(s).operator->();
  		// and increment reference count
  		if (ptr)
  			inc_ref_count(ptr);
  	}
  public:
  	// void kill() { ptr = 0; }
  	/// return the reference count
  	int get_count() const	{ 
  		return ptr ? ptr->get_ref_count() : 0; 
  	}
  };
  
  /** reference counted pointer, which can work together with types that are derived
      from ref_counted, in which case the reference count of ref_counted is
  	used. Otherwise a reference count is allocated and access to the stored instance
  	needs to follow two pointers. */
  template <class T, bool is_ref_counted = type::cond::is_base_of<ref_counted,T>::value>
  class ref_ptr : public ref_ptr_impl<T,is_ref_counted>
  {
  public:
  	/// type of the reference counted pointer
  	typedef ref_ptr<T,is_ref_counted> this_type;
  	/// type of base class that implements the reference count specific methods
  	typedef ref_ptr_impl<T,is_ref_counted> base_type;
  public:
  	/// construction from pointer or empty if pointer is not given
  	ref_ptr(T* p = 0) : base_type(p) {}
  	/// copy constructor for reference pointers of the same type
  	ref_ptr(const this_type& r) : base_type(r) {}
  	/// destruct reference counted pointer
     ~ref_ptr() { 
  		this->release();
  	}
  	/// allow to copy ref_ptr<S> to a ref_ptr<T> if T is a base class of S and if T has a virtual destructor
  	template <typename S>
  	ref_ptr(const ref_ptr<S,is_ref_counted>& s) : base_type(s) {}
  	/// use static cast to convert from T to S if T is a base class of S and has a virtual destructor
  	template <typename S>
  	ref_ptr<S,is_ref_counted> up_cast() const {
  		// ref_ptr conversion only valid if T is base of S
  		CGV_DEFINES_ASSERT(type::cond::is_base_of<T,S>::value);
  		// and S has a virtual destructor
  		CGV_DEFINES_ASSERT(type::cond::has_virtual_destructor<T>::value);
  		// after validity checks, return converted pointer
  		return ref_ptr<S,is_ref_counted>(
  					*reinterpret_cast<const ref_ptr<S,is_ref_counted>*>(this)
  				 );
  	}
  	/// assignment to pointer of same type
  	this_type& operator = (const this_type& r) {
  		if (this == &r)
  			return *this;
  		this->release();
  		new (this) this_type(r);
  		return *this;
  	}
  	/// assignment to pointer of derived type with virtual destructor
  	template <typename S>
  	this_type& operator = (const ref_ptr<S,is_ref_counted>& r) {
  		if (this == (const this_type*)&r)
  			return *this;
  		return *this = this_type(r);
  	}
  	/// access to element
  	T& operator*() const { 
  		return *this->ref();
  	}
  	/// access to element pointer
     T* operator->() const {
  		return this->ref();
  	}
  	/// compare by pointer
  	bool operator == (const this_type& r) const { 
  		return this->ref() == r.ref(); 
  	}
  	/// compare by pointer
  	bool operator < (const this_type& r) const { 
  		return this->ref() < r.ref(); 
  	}
  	/// compare by pointer
  	bool operator != (const this_type& r) const { 
  		return this->ref() != r.ref(); 
  	}
  	/// check if this is the only reference
  	bool unique() const {
  		return this->get_count() <= 1; 
  	}
  	/// check if pointer is not yet set
  	bool empty() const { 
  		return this->get_count() == 0; 
  	}
  	/// conversion to bool results in false if the stored pointer is a null pointer
  	operator bool () const {
  		return !empty();
  	}
  	/// set to null pointer
  	void clear() { 
  		this->release();
  	}
  };
  
  	}
  }
  
  #include <cgv/config/lib_end.h>