From 47cb94a3ef7a278407ab598a881c4e8f1b4d1054 Mon Sep 17 00:00:00 2001 From: Alan Conway Date: Fri, 18 Jan 2008 21:44:55 +0000 Subject: qpid/IList.h: Added public T* getNext(), T* getPrev() to IListNode so node subclasses can follow their own links. git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk@613290 13f79535-47bb-0310-9956-ffa450edef68 --- qpid/cpp/src/qpid/IList.h | 30 +++++++++++++++++++++--------- qpid/cpp/src/tests/IList.cpp | 18 ++++++++++++++++-- 2 files changed, 37 insertions(+), 11 deletions(-) (limited to 'qpid/cpp/src') diff --git a/qpid/cpp/src/qpid/IList.h b/qpid/cpp/src/qpid/IList.h index 5467a708d1..c0c8b503f0 100644 --- a/qpid/cpp/src/qpid/IList.h +++ b/qpid/cpp/src/qpid/IList.h @@ -43,15 +43,25 @@ template class IList; * IList - uses the 0 links * IList - uses the 1 links *@endcode + * + *@param T The derived class. + *@param N ID for multiple inheritance. */ -template class IListNode : public virtual RefCounted { +template class IListNode : public virtual RefCounted { intrusive_ptr prev; intrusive_ptr next; void insert(IListNode*); void erase(); - template friend class IList; + virtual T* self() const { // Virutal so anchor can hide. + return boost::polymorphic_downcast(const_cast(this)); + } + friend class IList; public: IListNode(IListNode* p=0) : prev(p), next(p) {} + T* getNext() { return next ? next->self() : 0; } + T* getPrev() { return prev ? prev->self() : 0; } + const T* getNext() const { return next ? next->self() : 0; } + const T* getPrev() const { return prev ? prev->self() : 0; } }; /** @@ -62,7 +72,7 @@ template class IListNode : public virtual RefCounted { */ template class IList { private: - typedef IListNode Node; + typedef IListNode Node; template class Iterator : @@ -109,7 +119,7 @@ template class IList { const_iterator last() const { return const_iterator(anchor.prev.get()); } /// Note: takes a non-const reference, unlike standard containers. - void insert(iterator pos, reference x) { x.IListNode::insert(pos.ptr); } + void insert(iterator pos, reference x) { x.Node::insert(pos.ptr); } void erase(iterator pos) { pos.ptr->erase(); } void swap(IList &x) { anchor.swap(x.anchor); } @@ -147,11 +157,13 @@ template class IList { Anchor() : Node(this) {} // Suppress refcounting for the anchor node. void release() const {} + // Hide anchor from public get functions. + T* self() const { return 0; } } anchor; }; -template -void IListNode::insert(IListNode* node) { +template +void IListNode::insert(IListNode* node) { assert(!next && !prev); // Not already in a list. assert(node); assert(node->next && node->prev); @@ -161,10 +173,10 @@ void IListNode::insert(IListNode* node) { next->prev = this; } -template -void IListNode::erase() { +template +void IListNode::erase() { assert(prev && next); - intrusive_ptr self(this); // Protect till exit. + intrusive_ptr save(this); // Protect till exit. prev->next = next; next->prev = prev; prev = next = 0; diff --git a/qpid/cpp/src/tests/IList.cpp b/qpid/cpp/src/tests/IList.cpp index ed36228828..f5d7cd344e 100644 --- a/qpid/cpp/src/tests/IList.cpp +++ b/qpid/cpp/src/tests/IList.cpp @@ -49,7 +49,9 @@ struct TestNode { int TestNode::instances = 0; ostream& operator<<(ostream& o, const TestNode& n) { return o << n.id; } -struct SingleNode : public TestNode, public IListNode<> { SingleNode(char i) : TestNode(i) {} }; +struct SingleNode : public TestNode, public IListNode { + SingleNode(char i) : TestNode(i) {} +}; typedef IList TestList; struct Fixture { @@ -119,8 +121,16 @@ BOOST_FIXTURE_TEST_CASE(TestIterator, Fixture) { { TestList l; l.push_back(*a); + BOOST_CHECK(a->getNext() == 0); + BOOST_CHECK(a->getPrev() == 0); l.push_back(*b); + BOOST_CHECK(a->getNext() == b.get()); + BOOST_CHECK(a->getPrev() == 0); + BOOST_CHECK(b->getNext() == 0); + BOOST_CHECK(b->getPrev() == a.get()); l.push_back(*c); + BOOST_CHECK(b->getNext() == c.get()); + BOOST_CHECK(c->getPrev() == b.get()); TestList::iterator i = l.begin(); BOOST_CHECK_EQUAL(*i, *a); @@ -155,7 +165,11 @@ BOOST_FIXTURE_TEST_CASE(testOwnership, Fixture) { BOOST_CHECK_EQUAL(0, SingleNode::instances); } -struct MultiNode : public TestNode, public IListNode<0>, public IListNode<1>, public IListNode<2> { +struct MultiNode : public TestNode, + public IListNode, + public IListNode, + public IListNode +{ MultiNode(char c) : TestNode(c) {} }; -- cgit v1.2.1