X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2FMoof%2Fstlplus%2Fsafe_iterator.tpp;fp=src%2FMoof%2Fstlplus%2Fsafe_iterator.tpp;h=14d89b992b30b7af42868fd3a2411c222d93bba9;hp=0000000000000000000000000000000000000000;hb=72d4af22710317acffab861421c4364b1780b6fe;hpb=493ddb59a8620b49dfa0ff62ce93395ebfd02e86 diff --git a/src/Moof/stlplus/safe_iterator.tpp b/src/Moof/stlplus/safe_iterator.tpp new file mode 100755 index 0000000..14d89b9 --- /dev/null +++ b/src/Moof/stlplus/safe_iterator.tpp @@ -0,0 +1,373 @@ +namespace stlplus +{ + + //////////////////////////////////////////////////////////////////////////////// + // body class implements the aliasing behaviour + + template + class safe_iterator_body + { + private: + const O* m_owner; + N* m_node; + unsigned m_count; + + public: + + safe_iterator_body(const O* owner, N* node) throw() : + m_owner(owner), m_node(node), m_count(1) + { +// std::cerr << "constructing " +// << std::hex << ((unsigned long)this) +// << " => " << ((unsigned long)m_owner) << ":" << ((unsigned long)m_node) +// << ":" << std::dec << m_count << std::endl; + } + + ~safe_iterator_body(void) throw() + { +// std::cerr << "destroying " +// << std::hex << ((unsigned long)this) +// << " => " << ((unsigned long)m_owner) << ":" << ((unsigned long)m_node) +// << ":" << std::dec << m_count << std::endl; + m_owner = 0; + m_node = 0; + } + + unsigned count(void) const + { + return m_count; + } + + void increment(void) + { + ++m_count; +// std::cerr << "incremented " +// << std::hex << ((unsigned long)this) +// << " => " << ((unsigned long)m_owner) << ":" << ((unsigned long)m_node) +// << ":" << std::dec << m_count << std::endl; + } + + bool decrement(void) + { + --m_count; +// std::cerr << "decremented " +// << std::hex << ((unsigned long)this) +// << " => " << ((unsigned long)m_owner) << ":" << ((unsigned long)m_node) +// << ":" << std::dec << m_count << std::endl; + return m_count == 0; + } + + N* node(void) const throw() + { + return m_node; + } + + const O* owner(void) const throw() + { + return m_owner; + } + + void change_owner(const O* owner) + { + m_owner = owner; + } + + bool equal(const safe_iterator_body* right) const throw() + { +// return m_node == right->m_node; + return compare(right) == 0; + } + + int compare(const safe_iterator_body* right) const throw() + { + return ((long)m_node) - ((long)right->m_node); + } + + bool null(void) const throw() + { + return m_owner == 0; + } + + bool end(void) const throw() + { + return m_owner != 0 && m_node == 0; + } + + bool valid(void) const throw() + { + return m_owner != 0 && m_node != 0; + } + + void set_end(void) throw() + { + m_node = 0; + } + + void set_null(void) throw() + { + m_owner = 0; + m_node = 0; + } + + void assert_valid(void) const throw(null_dereference,end_dereference) + { + if (null()) + throw null_dereference("stlplus::safe_iterator"); + if (end()) + throw end_dereference("stlplus::safe_iterator"); + } + + void assert_non_null(void) const throw(null_dereference) + { + if (null()) + throw null_dereference("stlplus::safe_iterator"); + } + + void assert_owner(const O* owner) const throw(wrong_object) + { + if (owner != m_owner) + throw wrong_object("stlplus::safe_iterator"); + } + }; + + + //////////////////////////////////////////////////////////////////////////////// + // Master Iterator + //////////////////////////////////////////////////////////////////////////////// + + // construct a valid iterator + template + master_iterator::master_iterator(const O* owner, N* node) throw() : + m_body(new safe_iterator_body(owner,node)) + { + } + + // destructor - disconnect all iterators from the node + // this usually happens when the node is deleted and must invalidate all aliases + template + master_iterator::~master_iterator(void) throw() + { + m_body->set_end(); + if(m_body->decrement()) + { + delete m_body; + m_body = 0; + } + } + + // dereference + template + N* master_iterator::node(void) const throw() + { + return m_body->node(); + } + + template + const O* master_iterator::owner(void) const throw() + { + return m_body->owner(); + } + + // when you move a node from one owner to another, call this on the node's iterator + // this effectively moves all iterators to the node so that they are owned by the new owner too + template + void master_iterator::change_owner(const O* owner) throw() + { + m_body->change_owner(owner); + } + + //////////////////////////////////////////////////////////////////////////////// + // Safe Iterator + //////////////////////////////////////////////////////////////////////////////// + + // construct a null iterator + // later assignment of a valid iterator to this is done by using step + template + safe_iterator::safe_iterator(void) throw() : + m_body(new safe_iterator_body(0,0)) + { + } + + // construct a valid iterator by aliasing from the owner node's master iterator + template + safe_iterator::safe_iterator(const master_iterator& r) throw() : + m_body(0) + { + m_body = r.m_body; + m_body->increment(); + } + + // construct a valid iterator by aliasing from the owner node's master iterator + template + safe_iterator::safe_iterator(const safe_iterator& r) throw() : + m_body(0) + { + m_body = r.m_body; + m_body->increment(); + } + + // assignment implements dealiasing followed by aliasing + template + safe_iterator& safe_iterator::operator=(const safe_iterator& r) throw() + { + if (m_body != r.m_body) + { + if (m_body->decrement()) + delete m_body; + m_body = r.m_body; + m_body->increment(); + } + return *this; + } + + // destructor - implements dealiasing + template + safe_iterator::~safe_iterator(void) throw() + { + if(m_body->decrement()) + { + delete m_body; + m_body = 0; + } + } + + + // increment/decrement operation + // implements dealiasing followed by aliasing + template + void safe_iterator::set(const master_iterator& r) throw() + { + if (m_body != r.m_body) + { + if (m_body->decrement()) + delete m_body; + m_body = r.m_body; + m_body->increment(); + } + } + + // dereference + template + N* safe_iterator::node(void) const throw() + { + return m_body->node(); + } + + template + const O* safe_iterator::owner(void) const throw() + { + return m_body->owner(); + } + + // change to a null iterator - i.e. one that doees not belong to any object + // this does not affect any other iterators pointing to the same node + template + void safe_iterator::set_null(void) throw() + { + if (m_body->count() == 1) + { + // no aliases, so just make this null + m_body->set_null(); + } + else + { + // create a new body which is null so as not to affect any other aliases + m_body->decrement(); + m_body = new safe_iterator_body(0,0); + } + } + + //////////////////////////////////////////////////////////////////////////////// + // operations for clients that do not have a master end iterator + // alternatively, have a master end iterator as part of the container + // and call constructor(master_end) or step(master_end) + + // construct an end iterator + template + safe_iterator::safe_iterator(const O* owner) throw() : + m_body(new safe_iterator_body(owner,0)) + { + } + + // change to an end iterator - e.g. as a result of incrementing off the end + template + void safe_iterator::set_end(void) throw() + { + if (m_body->count() == 1) + { + // no aliases, so just make this an end iterator + m_body->set_end(); + } + else + { + // create a new body which is null so as not to affect any other aliases + m_body->decrement(); + m_body = new safe_iterator_body(owner(),0); + } + } + + //////////////////////////////////////////////////////////////////////////////// + // tests + + // comparison + template + bool safe_iterator::equal(const safe_iterator& right) const throw() + { + return compare(right) == 0; + } + + template + int safe_iterator::compare(const safe_iterator& right) const throw() + { + if (m_body == right.m_body) return 0; + return m_body->compare(right.m_body); + } + + // a null iterator is one that has not been initialised with a value yet + template + bool safe_iterator::null(void) const throw() + { + return m_body->null(); + } + + // an end iterator is one that points to the end element of the list of nodes + template + bool safe_iterator::end(void) const throw() + { + return m_body->end(); + } + + // a valid iterator is one that can be dereferenced + template + bool safe_iterator::valid(void) const throw() + { + return m_body->valid(); + } + + // check the rules for a valid iterator that can be dereferenced + template + void safe_iterator::assert_valid(void) const throw(null_dereference,end_dereference) + { + m_body->assert_valid(); + } + + template + void safe_iterator::assert_valid(const O* owner) const throw(wrong_object,null_dereference,end_dereference) + { + m_body->assert_valid(); + m_body->assert_owner(owner); + } + + template + void safe_iterator::assert_non_null(void) const throw(null_dereference) + { + m_body->assert_non_null(); + } + + template + void safe_iterator::assert_owner(const O* owner) const throw(wrong_object) + { + m_body->assert_owner(owner); + } + +} // end namespace stlplus