X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2Fstlplus%2Fcontainers%2Fsmart_ptr.tpp;h=3af02101e92303c3cddf66b78a4fbe70730a16e6;hp=ce72da22879a0af1d403fa64804c11591a400ac0;hb=5846afb00833cc72fe72422ca896d2387c712cb4;hpb=a97500609dc3c1b11f9786d32bc458eb00de4c36 diff --git a/src/stlplus/containers/smart_ptr.tpp b/src/stlplus/containers/smart_ptr.tpp index ce72da2..3af0210 100644 --- a/src/stlplus/containers/smart_ptr.tpp +++ b/src/stlplus/containers/smart_ptr.tpp @@ -1,345 +1,345 @@ -//////////////////////////////////////////////////////////////////////////////// - -// 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(); - } - - // assignment operator - required, else the output of GCC suffers segmentation faults - template - smart_ptr_base& smart_ptr_base::operator=(const smart_ptr_base& r) - { - alias(r); - return *this; - } - - // 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_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 - smart_ptr_holder* smart_ptr_base::_handle(void) const - { - return m_holder; - } - - template - void smart_ptr_base::_make_alias(smart_ptr_holder* r_holder) - { - // 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_holder) - { - if (m_holder->decrement()) - delete m_holder; - m_holder = r_holder; - m_holder->increment(); - } - } - - //////////////////////////////////////////////////////////////////////////////// - -} // end namespace stlplus - +//////////////////////////////////////////////////////////////////////////////// + +// 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(); + } + + // assignment operator - required, else the output of GCC suffers segmentation faults + template + smart_ptr_base& smart_ptr_base::operator=(const smart_ptr_base& r) + { + alias(r); + return *this; + } + + // 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_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 + smart_ptr_holder* smart_ptr_base::_handle(void) const + { + return m_holder; + } + + template + void smart_ptr_base::_make_alias(smart_ptr_holder* r_holder) + { + // 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_holder) + { + if (m_holder->decrement()) + delete m_holder; + m_holder = r_holder; + m_holder->increment(); + } + } + + //////////////////////////////////////////////////////////////////////////////// + +} // end namespace stlplus +