diff --git a/include/etl/intrusive_links.h b/include/etl/intrusive_links.h index 5c9544bf..69012668 100644 --- a/include/etl/intrusive_links.h +++ b/include/etl/intrusive_links.h @@ -944,7 +944,7 @@ namespace etl { TLink* current = &first; ((current->etl_next = &links, static_cast(links).etl_previous = current, current = &links), ...); - + return current; } @@ -1303,16 +1303,30 @@ namespace etl typename etl::enable_if >::value, void>::type link_rotate_left(TLink& parent, TLink& leaf) { - parent.etl_right = leaf.etl_left; + TLink* grandparent = parent.etl_parent; - if (parent.etl_right != ETL_NULLPTR) - { - parent.etl_right->etl_parent = &parent; - } + parent.etl_right = leaf.etl_left; - leaf.etl_parent = parent.etl_parent; - parent.etl_parent = &leaf; - leaf.etl_left = &parent; + if (parent.etl_right != ETL_NULLPTR) + { + parent.etl_right->etl_parent = &parent; + } + + leaf.etl_parent = grandparent; + parent.etl_parent = &leaf; + leaf.etl_left = &parent; + + if (grandparent != ETL_NULLPTR) + { + if (grandparent->etl_left == &parent) + { + grandparent->etl_left = &leaf; + } + else if (grandparent->etl_right == &parent) + { + grandparent->etl_right = &leaf; + } + } } //*********************************** @@ -1358,19 +1372,32 @@ namespace etl typename etl::enable_if >::value, void>::type link_rotate_right(TLink& parent, TLink& leaf) { - parent.etl_left = leaf.etl_right; + TLink* grandparent = parent.etl_parent; - if (parent.etl_left != ETL_NULLPTR) - { - parent.etl_left->etl_parent = &parent; - } + parent.etl_left = leaf.etl_right; - leaf.etl_parent = parent.etl_parent; - parent.etl_parent = &leaf; - leaf.etl_right = &parent; + if (parent.etl_left != ETL_NULLPTR) + { + parent.etl_left->etl_parent = &parent; + } + + leaf.etl_parent = grandparent; + parent.etl_parent = &leaf; + leaf.etl_right = &parent; + + if (grandparent != ETL_NULLPTR) + { + if (grandparent->etl_left == &parent) + { + grandparent->etl_left = &leaf; + } + else if (grandparent->etl_right == &parent) + { + grandparent->etl_right = &leaf; + } + } } - template typename etl::enable_if >::value, void>::type link_rotate_right(TLink* parent, TLink* leaf) diff --git a/test/test_intrusive_links.cpp b/test/test_intrusive_links.cpp index c5bb92c8..2407b724 100644 --- a/test/test_intrusive_links.cpp +++ b/test/test_intrusive_links.cpp @@ -554,7 +554,7 @@ namespace CHECK(data1.FLink0::etl_next == &data2); CHECK(data2.FLink0::etl_next == nullptr); CHECK(data3.FLink0::etl_next == nullptr); - + etl::link_clear_range(*start); CHECK(data0.FLink0::etl_next == &data3); CHECK(data1.FLink0::etl_next == nullptr); @@ -882,11 +882,11 @@ namespace BData data2(2); BData data3(3); - // Use reference interface + // Use reference interface data0.BLink0::set_next(data1); data1.BLink0::set_next(data2); data2.BLink0::set_next(data3); - + data1.BLink0::set_previous(data0); data2.BLink0::set_previous(data1); data3.BLink0::set_previous(data2); @@ -1625,17 +1625,45 @@ namespace etl::link_right(a, c); etl::link_left(a, e); + // r // + // / // + // b // + // / \ // + // d a // + // / \ // + // e c // + etl::link_rotate_left(b, a); + // r // + // / // + // a // + // / \ // + // b c // + // / \ // + // d e // + + CHECK(r.etl_left == &a); + CHECK(a.etl_parent == &r); - CHECK(b.etl_parent == &a); - CHECK(e.etl_parent == &b); - CHECK(d.etl_parent == &b); - CHECK(c.etl_parent == &a); CHECK(a.etl_left == &b); CHECK(a.etl_right == &c); + + CHECK(b.etl_parent == &a); CHECK(b.etl_left == &d); CHECK(b.etl_right == &e); + + CHECK(d.etl_parent == &b); + CHECK(d.etl_left == nullptr); + CHECK(d.etl_right == nullptr); + + CHECK(c.etl_parent == &a); + CHECK(c.etl_left == nullptr); + CHECK(c.etl_right == nullptr); + + CHECK(e.etl_parent == &b); + CHECK(e.etl_left == nullptr); + CHECK(e.etl_right == nullptr); } //************************************************************************* @@ -1656,16 +1684,41 @@ namespace etl::link_left(b, d); etl::link_right(a, c); + // r // + // / // + // b // + // / \ // + // d a // + // \ // + // c // + etl::link_rotate_left(b, a); + // r // + // / // + // a // + // / \ // + // b c // + // / // + // d // + + CHECK(r.etl_left == &a); + CHECK(a.etl_parent == &r); - CHECK(b.etl_parent == &a); - CHECK(d.etl_parent == &b); - CHECK(c.etl_parent == &a); CHECK(a.etl_left == &b); CHECK(a.etl_right == &c); + + CHECK(b.etl_parent == &a); CHECK(b.etl_left == &d); CHECK(b.etl_right == nullptr); + + CHECK(d.etl_parent == &b); + CHECK(d.etl_left == nullptr); + CHECK(d.etl_right == nullptr); + + CHECK(c.etl_parent == &a); + CHECK(c.etl_left == nullptr); + CHECK(c.etl_right == nullptr); } //************************************************************************* @@ -1684,21 +1737,49 @@ namespace e.clear(); etl::link_left(r, a); etl::link_left(a, b); - etl::link_left(b, d); etl::link_right(a, c); + etl::link_left(b, d); etl::link_right(b, e); + // r // + // / // + // a // + // / \ // + // b c // + // / \ // + // d e // + etl::link_rotate_right(a, b); + // r // + // / // + // b // + // / \ // + // d a // + // / \ // + // e c // + + CHECK(r.etl_left == &b); + CHECK(b.etl_parent == &r); - CHECK(d.etl_parent == &b); - CHECK(a.etl_parent == &b); - CHECK(e.etl_parent == &a); - CHECK(c.etl_parent == &a); CHECK(b.etl_left == &d); CHECK(b.etl_right == &a); + + CHECK(d.etl_parent == &b); + CHECK(d.etl_left == nullptr); + CHECK(d.etl_right == nullptr); + + CHECK(a.etl_parent == &b); CHECK(a.etl_left == &e); CHECK(a.etl_right == &c); + + CHECK(c.etl_parent == &a); + CHECK(c.etl_left == nullptr); + CHECK(c.etl_right == nullptr); + + CHECK(e.etl_parent == &a); + CHECK(e.etl_left == nullptr); + CHECK(e.etl_right == nullptr); } //************************************************************************* @@ -1719,16 +1800,41 @@ namespace etl::link_left(b, d); etl::link_right(a, c); + // r // + // / // + // a // + // / \ // + // b c // + // / // + // d // + etl::link_rotate_right(a, b); + // r // + // / // + // b // + // / \ // + // d a // + // \ // + // c // + + CHECK(r.etl_left == &b); + CHECK(b.etl_parent == &r); - CHECK(d.etl_parent == &b); - CHECK(a.etl_parent == &b); - CHECK(c.etl_parent == &a); CHECK(b.etl_left == &d); CHECK(b.etl_right == &a); + + CHECK(d.etl_parent == &b); + CHECK(d.etl_left == nullptr); + CHECK(d.etl_right == nullptr); + + CHECK(a.etl_parent == &b); CHECK(a.etl_left == nullptr); CHECK(a.etl_right == &c); + + CHECK(c.etl_parent == &a); + CHECK(c.etl_left == nullptr); + CHECK(c.etl_right == nullptr); } } }