From 1623de8bd07e801333aa954d3cb195c0a296fa71 Mon Sep 17 00:00:00 2001 From: Daniel Agar Date: Tue, 11 Jun 2019 14:38:28 -0400 Subject: [PATCH] IntrusiveQueue add remove method, iterators, and update test --- src/include/containers/IntrusiveQueue.hpp | 52 ++++++++++++++++++ src/systemcmds/tests/test_IntrusiveQueue.cpp | 57 ++++++++++++++++++++ 2 files changed, 109 insertions(+) diff --git a/src/include/containers/IntrusiveQueue.hpp b/src/include/containers/IntrusiveQueue.hpp index 100017cd29..47f2099725 100644 --- a/src/include/containers/IntrusiveQueue.hpp +++ b/src/include/containers/IntrusiveQueue.hpp @@ -95,6 +95,58 @@ public: return ret; } + bool remove(T removeNode) + { + // base case + if (removeNode == _head) { + if (_head->next_intrusive_queue_node() != nullptr) { + _head = _head->next_intrusive_queue_node(); + + } else { + _head = nullptr; + } + + return true; + } + + for (T node = _head; node != nullptr; node = node->next_intrusive_queue_node()) { + // is sibling the node to remove? + if (node->next_intrusive_queue_node() == removeNode) { + // replace sibling + if (node->next_intrusive_queue_node() != nullptr) { + node->set_next_intrusive_queue_node(node->next_intrusive_queue_node()->next_intrusive_queue_node()); + + } else { + node->set_next_intrusive_queue_node(nullptr); + } + + return true; + } + } + + return false; + } + + struct Iterator { + T node; + Iterator(T v) : node(v) {} + + operator T() const { return node; } + operator T &() { return node; } + T operator* () const { return node; } + Iterator &operator++ () + { + if (node) { + node = node->next_intrusive_queue_node(); + }; + + return *this; + } + }; + + Iterator begin() { return Iterator(_head); } + Iterator end() { return Iterator(nullptr); } + private: T _head{nullptr}; diff --git a/src/systemcmds/tests/test_IntrusiveQueue.cpp b/src/systemcmds/tests/test_IntrusiveQueue.cpp index d82f7607f4..6c7005cc1d 100644 --- a/src/systemcmds/tests/test_IntrusiveQueue.cpp +++ b/src/systemcmds/tests/test_IntrusiveQueue.cpp @@ -50,6 +50,7 @@ public: bool test_push(); bool test_pop(); bool test_push_duplicate(); + bool test_remove(); }; @@ -58,6 +59,7 @@ bool IntrusiveQueueTest::run_tests() ut_run_test(test_push); ut_run_test(test_pop); ut_run_test(test_push_duplicate); + ut_run_test(test_remove); return (_tests_failed == 0); } @@ -211,4 +213,59 @@ bool IntrusiveQueueTest::test_push_duplicate() return true; } +bool IntrusiveQueueTest::test_remove() +{ + IntrusiveQueue q1; + + // size should be 0 initially + ut_compare("size initially 0", q1.size(), 0); + ut_assert_true(q1.empty()); + + // insert 100 + for (int i = 0; i < 100; i++) { + testContainer *t = new testContainer(); + t->i = i; + q1.push(t); + + ut_compare("size increasing with i", q1.size(), i + 1); + ut_assert_true(!q1.empty()); + } + + // verify full size (100) + ut_assert_true(q1.size() == 100); + + // test removing elements + for (int remove_i = 0; remove_i < 100; remove_i++) { + + // find node with i == remove_i + for (auto t : q1) { + if (t->i == remove_i) { + ut_assert_true(q1.remove(t)); + } + } + + // iterate list again to verify removal + for (auto t : q1) { + ut_assert_true(t->i != remove_i); + } + + ut_assert_true(q1.size() == 100 - remove_i - 1); + } + + // list should now be empty + ut_assert_true(q1.empty()); + ut_compare("size 0", q1.size(), 0); + + // delete all elements (should be safe on empty list) + while (!q1.empty()) { + q1.pop(); + } + + // verify list has been cleared + ut_assert_true(q1.empty()); + ut_compare("size 0", q1.size(), 0); + + return true; +} + ut_declare_test_c(test_IntrusiveQueue, IntrusiveQueueTest)