X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2FMoof%2Fstlplus%2Fsmart_ptr.tpp;fp=src%2FMoof%2Fstlplus%2Fsmart_ptr.tpp;h=cb1b8bbb825886754779bebcf2aabcc0980a793a;hp=0000000000000000000000000000000000000000;hb=72d4af22710317acffab861421c4364b1780b6fe;hpb=493ddb59a8620b49dfa0ff62ce93395ebfd02e86 diff --git a/src/Moof/stlplus/smart_ptr.tpp b/src/Moof/stlplus/smart_ptr.tpp new file mode 100755 index 0000000..cb1b8bb --- /dev/null +++ b/src/Moof/stlplus/smart_ptr.tpp @@ -0,0 +1,343 @@ +//////////////////////////////////////////////////////////////////////////////// + +// Author: Andy Rushton +// Copyright: (c) Southampton University 1999-2004 +// (c) Andy Rushton 2004-2009 +// License: BSD License, see ../docs/license.html + +//////////////////////////////////////////////////////////////////////////////// + +namespace stlplus +{ + + //////////////////////////////////////////////////////////////////////////////// + // internal holder data structure + //////////////////////////////////////////////////////////////////////////////// + + template + class smart_ptr_holder + { + private: + unsigned m_count; + T* m_data; + + // make these private to disallow copying because the holder doesn't know how to copy + smart_ptr_holder(const smart_ptr_holder& s) : + m_count(0), m_data(0) + { + } + + smart_ptr_holder& operator=(const smart_ptr_holder& s) + { + return *this; + } + + public: + smart_ptr_holder(T* p = 0) : + m_count(1), m_data(p) + { + } + + ~smart_ptr_holder(void) + { + clear(); + } + + unsigned count(void) const + { + return m_count; + } + + void increment(void) + { + ++m_count; + } + + bool decrement(void) + { + --m_count; + return m_count == 0; + } + + bool null(void) + { + return m_data == 0; + } + + void clear(void) + { + if(m_data) + delete m_data; + m_data = 0; + } + + void set(T* p = 0) + { + clear(); + m_data = p; + } + + T*& pointer(void) + { + return m_data; + } + + const T* pointer(void) const + { + return m_data; + } + + T& value(void) + { + return *m_data; + } + + const T& value(void) const + { + return *m_data; + } + }; + + //////////////////////////////////////////////////////////////////////////////// + // smart_ptr_base class + //////////////////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////////////////// + // constructors, assignments and destructors + + // create a null pointer + template + smart_ptr_base::smart_ptr_base(void) : + m_holder(new smart_ptr_holder) + { + } + + // create a pointer containing a *copy* of the object pointer + template + smart_ptr_base::smart_ptr_base(const T& data) throw(illegal_copy) : + m_holder(new smart_ptr_holder) + { + m_holder->set(C()(data)); + } + + // create a pointer containing a dynamically created object + // Note: the object must be allocated *by the user* with new + // constructor form - must be called in the form smart_ptr x(new type(args)) + template + smart_ptr_base::smart_ptr_base(T* data) : + m_holder(new smart_ptr_holder) + { + m_holder->set(data); + } + + // copy constructor implements counted referencing - no copy is made + template + smart_ptr_base::smart_ptr_base(const smart_ptr_base& r) : + m_holder(0) + { + m_holder = r.m_holder; + m_holder->increment(); + } + + // destructor decrements the reference count and delete only when the last reference is destroyed + template + smart_ptr_base::~smart_ptr_base(void) + { + if(m_holder->decrement()) + delete m_holder; + } + + ////////////////////////////////////////////////////////////////////////////// + // logical tests to see if there is anything contained in the pointer since it can be null + + template + bool smart_ptr_base::null(void) const + { + return m_holder->null(); + } + + template + bool smart_ptr_base::present(void) const + { + return !m_holder->null(); + } + + template + bool smart_ptr_base::operator!(void) const + { + return m_holder->null(); + } + + template + smart_ptr_base::operator bool(void) const + { + return !m_holder->null(); + } + + ////////////////////////////////////////////////////////////////////////////// + // dereference operators and functions + + template + T& smart_ptr_base::operator*(void) throw(null_dereference) + { + if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator*"); + return m_holder->value(); + } + + template + const T& smart_ptr_base::operator*(void) const throw(null_dereference) + { + if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator*"); + return m_holder->value(); + } + + template + T* smart_ptr_base::operator->(void) throw(null_dereference) + { + if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator->"); + return m_holder->pointer(); + } + + template + const T* smart_ptr_base::operator->(void) const throw(null_dereference) + { + if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator->"); + return m_holder->pointer(); + } + + ////////////////////////////////////////////////////////////////////////////// + // explicit function forms of the above assignment dereference operators + + template + void smart_ptr_base::set_value(const T& data) throw(illegal_copy) + { + m_holder->set(C()(data)); + } + + template + T& smart_ptr_base::value(void) throw(null_dereference) + { + if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::value"); + return m_holder->value(); + } + + template + const T& smart_ptr_base::value(void) const throw(null_dereference) + { + if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::value"); + return m_holder->value(); + } + + template + void smart_ptr_base::set(T* data) + { + m_holder->set(data); + } + + template + T* smart_ptr_base::pointer(void) + { + return m_holder->pointer(); + } + + template + const T* smart_ptr_base::pointer(void) const + { + return m_holder->pointer(); + } + + //////////////////////////////////////////////////////////////////////////////// + // functions to manage counted referencing + + // make this an alias of the passed object + template + void smart_ptr_base::alias(const smart_ptr_base& r) + { + // make it alias-copy safe - this means that I don't try to do the + // assignment if r is either the same object or an alias of it + // if (m_holder == r.m_holder) return; + // if (m_holder->decrement()) + // delete m_holder; + // m_holder = r.m_holder; + // m_holder->increment(); + make_alias(r.m_holder); + } + + template + bool smart_ptr_base::aliases(const smart_ptr_base& r) const + { + return m_holder == r.m_holder; + } + + template + unsigned smart_ptr_base::alias_count(void) const + { + return m_holder->count(); + } + + template + void smart_ptr_base::clear(void) + { + m_holder->clear(); + } + + template + void smart_ptr_base::clear_unique(void) + { + if (m_holder->count() == 1) + m_holder->clear(); + else + { + m_holder->decrement(); + m_holder = 0; + m_holder = new smart_ptr_holder; + } + } + + template + void smart_ptr_base::make_unique(void) throw(illegal_copy) + { + if (m_holder->count() > 1) + { + smart_ptr_holder* old_holder = m_holder; + m_holder->decrement(); + m_holder = 0; + m_holder = new smart_ptr_holder; + if (old_holder->pointer()) + m_holder->set(C()(old_holder->value())); + } + } + + template + void smart_ptr_base::copy(const smart_ptr_base& data) throw(illegal_copy) + { + alias(data); + make_unique(); + } + + // internal function for distinguishing unique smart_ptr objects + // used for example in persistence routines + + template + void* smart_ptr_base::handle(void) const + { + return m_holder; + } + + template + void smart_ptr_base::make_alias(void* handle) + { + smart_ptr_holder* r_holder = (smart_ptr_holder*)handle; + if (m_holder != r_holder) + { + if (m_holder->decrement()) + delete m_holder; + m_holder = r_holder; + m_holder->increment(); + } + } + + //////////////////////////////////////////////////////////////////////////////// + +} // end namespace stlplus +