diff --git a/mesosphere/include/mesosphere/core/KLinkedList.hpp b/mesosphere/include/mesosphere/core/KLinkedList.hpp index 32d288842..587d6fa70 100644 --- a/mesosphere/include/mesosphere/core/KLinkedList.hpp +++ b/mesosphere/include/mesosphere/core/KLinkedList.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include namespace mesosphere @@ -15,31 +16,50 @@ template class KLinkedList final { private: - struct List { - Node *last; - Node *first; + + struct List final { + struct Node final : public ISlabAllocated { + + struct Link final { + Link *prev = nullptr; + Link *next = nullptr; + + Node &parent() + { + return *detail::GetParentFromMember(this, &Node::link); + } + + const Node &parent() const + { + return *detail::GetParentFromMember(this, &Node::link); + } + + T &data() { return parent().data; } + const T &data() const { return parent().data; } + }; + + Link link{}; + T data{}; + + Node() = default; + Node(const Node &other) = default; + Node(Node &&other) = default; + explicit Node(const T &data) : ISlabAllocated(), data{data} {} + explicit Node(const T &&data) : ISlabAllocated(), data{data} {} + template + explicit Node(Args&& ...args) : ISlabAllocated(), data{std::forward(args)...} {} + }; + + mutable typename Node::Link link{}; + typename Node::Link *last() const { return link.prev; } + typename Node::Link *first() const { return link.next; } + size_t size = 0; }; List list; - struct Node final : public ISlabAllocated { - //friend class KLinkedList; - Node *prev = nullptr; - Node *next = nullptr; - T data{}; - - Node() = default; - Node(const Node &other) = default; - Node(Node &&other) = default; - explicit Node(const T &data) : Node(), data{other} {} - explicit Node(const T &&data) : Node(), data{other} {} - template - explicit Node(Args&& ...args) : Node(), data{std::forward(args)...} {} - }; - - - void insert_node_after(Node *pos, Node *nd) + void insert_node_after(typename List::Node::Link *pos, typename List::Node::Link *nd) { // if pos is last & list is empty, ->next writes to first, etc. pos->next->prev = nd; @@ -49,7 +69,7 @@ class KLinkedList final { ++list.size; } - void insert_node_before(Node *pos, Node *nd) + void insert_node_before(typename List::Node::Link *pos, typename List::Node::Link *nd) { pos->prev->next = nd; nd->prev = pos->prev; @@ -58,7 +78,7 @@ class KLinkedList final { ++list.size; } - void remove_node(Node *nd) + void remove_node(typename List::Node::Link *nd) { nd->prev->next = nd->next; nd->next->prev = nd->prev; @@ -95,12 +115,12 @@ class KLinkedList final { reference operator*() { - return node->data; + return node->data(); } pointer operator->() { - return &node->data; + return &node->data(); } Iterator &operator++() @@ -135,13 +155,15 @@ class KLinkedList final { private: friend class KLinkedList; - KLinkedList::Node *node; + typename KLinkedList::List::Node::Link *node; - explicit Iterator(KLinkedList::Node *node) : node{node} {} + explicit Iterator(typename KLinkedList::List::Node::Link *node) : node{node} {} }; using pointer = T *; using const_pointer = const T *; + using reference = T &; + using const_reference = const T &; using void_pointer = void *; using const_void_ptr = const void *; using value_type = T; @@ -152,41 +174,42 @@ class KLinkedList final { using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; - KLinkedList() : list{(Node *)&list, (Node *)&list} {}; + KLinkedList() : list{{&list.link, &list.link}} {}; explicit KLinkedList(size_t count, const T &value) : KLinkedList() { for (size_t i = 0; i < count; i++) { - Node *nd = new Node{value}; + auto *nd = new typename List::Node{value}; kassert(nd != nullptr); - insert_node_after(list.last, nd); + insert_node_after(list.last(), &nd->link); } } explicit KLinkedList(size_t count) : KLinkedList() { for (size_t i = 0; i < count; i++) { - Node *nd = new Node; + auto *nd = new typename List::Node; kassert(nd != nullptr); - insert_node_after(list.last, nd); + insert_node_after(list.last(), &nd->link); } } template>> - explicit KLinkedList(InputIt first, InputIt last) : KLinkedList() + KLinkedList(InputIt first, InputIt last) : KLinkedList() { for (InputIt it = first; it != last; ++it) { - Node *nd = new Node{*it}; + auto *nd = new typename List::Node{*it}; kassert(nd != nullptr); - insert_node_after(list.last, nd); + insert_node_after(list.last(), &nd->link); } } void swap(KLinkedList &other) noexcept { using std::swap; // Enable ADL - swap(list.first, other.list.first); - swap(list.last, other.list.last); + swap(list.link, other.list.link); swap(list.size, other.list.size); + list.first()->prev = list.last()->next = &list.link; + other.list.first()->prev = other.list.last()->next = &other.list.link; } KLinkedList(KLinkedList &&other) noexcept : KLinkedList() @@ -197,10 +220,10 @@ class KLinkedList final { void clear() noexcept { - Node *nxt; - for (Node nd = list.first; nd != (Node *)&list; nd = nxt) { + typename List::Node::Link *nxt; + for (typename List::Node::Link *nd = list.first(); nd != &list.link; nd = nxt) { nxt = nd->next; - delete nd; + delete &nd->parent(); } list.size = 0; } @@ -212,59 +235,59 @@ class KLinkedList final { KLinkedList &operator=(KLinkedList other) { - swap(*this, other); + swap(other); return *this; } KLinkedList &operator=(std::initializer_list ilist) { KLinkedList tmp{ilist}; - swap(*this, tmp); + swap(tmp); return *this; } void assign(size_t count, const T &value) { KLinkedList tmp{count, value}; - swap(*this, tmp); + swap(tmp); } template>> void assign(InputIt first, InputIt last) { KLinkedList tmp{first, last}; - swap(*this, tmp); + swap(tmp); } void assign(std::initializer_list ilist) { KLinkedList tmp{ilist}; - swap(*this, tmp); + swap(tmp); } - T &front() { return list.first->data; } - const T &front() const { return list.first->data; } + T &front() { return list.first()->data(); } + const T &front() const { return list.first()->data(); } - T &back() { return list.last->data; } - const T &back(); const { return list.last->data; } + T &back() { return list.last()->data(); } + const T &back() const { return list.last()->data(); } - const_iterator cbegin() const noexcept { return const_iterator{list.first}; } - const_iterator cend() const noexcept { return const_iterator{(Node *)&list}; } + const_iterator cbegin() const noexcept { return const_iterator{list.first()}; } + const_iterator cend() const noexcept { return const_iterator{&list.link}; } const_iterator begin() const noexcept { return cbegin(); } const_iterator end() const noexcept { return cend(); } - iterator begin() noexcept { return iterator{list.first}; } - iterator end() noexcept { return iterator{(Node *)&list}; } + iterator begin() noexcept { return iterator{list.first()}; } + iterator end() noexcept { return iterator{&list.link}; } - const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator{list.last}; } - const_reverse_iterator crend() const noexcept { return const_reverse_iterator{(Node *)&list}; } + const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator{list.last()}; } + const_reverse_iterator crend() const noexcept { return const_reverse_iterator{&list.link}; } const_reverse_iterator rbegin() const noexcept { return crbegin(); } const_reverse_iterator rend() const noexcept { return crend(); } - reverse_iterator rbegin() const noexcept { return reverse_iterator{list.last}; } - reverse_iterator rend() const noexcept { return reverse_iterator{(Node *)&list}; } + reverse_iterator rbegin() noexcept { return reverse_iterator{list.last()}; } + reverse_iterator rend() noexcept { return reverse_iterator{&list.link}; } KLinkedList(const KLinkedList &other) : KLinkedList(other.cbegin(), other.cend()) {} @@ -273,17 +296,17 @@ class KLinkedList final { iterator insert(const_iterator pos, const T &value) { - Node *nd = new Node{value}; + auto *nd = new typename List::Node{value}; kassert(nd != nullptr); - insert_node_after(pos.node, nd); + insert_node_after(pos.node, &nd->link); } iterator insert(const_iterator pos, T &&value) { - Node *nd = new Node{value}; + auto *nd = new typename List::Node{value}; kassert(nd != nullptr); - insert_node_before(pos.node, nd); - return iterator{nd}; + insert_node_before(pos.node, &nd->link); + return iterator{&nd->link}; } iterator insert(const_iterator pos, size_t count, const T &value) @@ -299,33 +322,38 @@ class KLinkedList final { iterator insert(const_iterator pos, InputIt first, InputIt last) { // Note: our list definition allows --begin() to be well defined - Node *f = nullptr; - Node *p = pos.node->prev; + typename List::Node::Link *f = nullptr; + typename List::Node::Link *p = pos.node->prev; for(InputIt it = first; it != last; ++it) { - Node *nd = new Node{value}; + auto *nd = new typename List::Node{*it}; kassert(nd != nullptr); - insert_node_after(p, nd); - p = nd; - f = f == nullptr ? nd : f; + insert_node_after(p, &nd->link); + p = &nd->link; + f = f == nullptr ? p : f; } return iterator{f}; } + iterator insert(const_iterator pos, std::initializer_list ilist) + { + return insert(pos, ilist.begin(), ilist.end()); + } + template iterator emplace(const_iterator pos, Args &&...args) { - Node *nd = new Node{std::forward(args)...}; + auto *nd = new typename List::Node{std::forward(args)...}; kassert(nd != nullptr); - insert_node_before(pos.node, nd); - return iterator{nd}; + insert_node_before(pos.node, &nd->link); + return iterator{&nd->link}; } iterator erase(const_iterator pos) { - iterator ret{pos->next}; + iterator ret{pos.node->next}; remove_node(pos.node); - delete pos.node; + delete &pos.node->parent(); return ret; } @@ -340,59 +368,62 @@ class KLinkedList final { void push_back(const T &value) { - Node *nd = new Node{value}; + auto *nd = new typename List::Node{value}; kassert(nd != nullptr); - insert_node_after(list.last, nd); + insert_node_after(list.last(), &nd->link); } void push_back(T &&value) { - Node *nd = new Node{value}; + auto *nd = new typename List::Node{value}; kassert(nd != nullptr); - insert_node_after(list.last, nd); + insert_node_after(list.last(), &nd->link); } template< class... Args> T &emplace_back(Args&&... args) { - Node *nd = new Node{std::forward(args)...}; + auto *nd = new typename List::Node{std::forward(args)...}; kassert(nd != nullptr); - insert_node_after(list.last, nd); + insert_node_after(list.last(), &nd->link); return nd->data; } void pop_back() { - remove_node(list.last); - delete list.last; + auto *nd = list.last(); + remove_node(nd); + delete &nd->parent(); } void push_front(const T &value) { - Node *nd = new Node{value}; + auto *nd = new typename List::Node{value}; kassert(nd != nullptr); - insert_node_before(list.first, nd); + insert_node_before(list.first(), &nd->link); } void push_front(T &&value) { - Node *nd = new Node{value}; + auto *nd = new typename List::Node{value}; kassert(nd != nullptr); - insert_node_before(list.first, nd); + insert_node_before(list.first(), &nd->link); } template< class... Args> T &emplace_front(Args&&... args) { - Node *nd = new Node{std::forward(args)...}; + auto *nd = new typename List::Node{std::forward(args)...}; kassert(nd != nullptr); - insert_node_before(list.first, nd); + insert_node_before(list.first(), &nd->link); return nd->data; } void pop_front() { - remove_node(list.first); + auto *nd = list.first(); + remove_node(nd); + delete &nd->parent(); } void resize(size_t count) @@ -402,10 +433,11 @@ class KLinkedList final { pop_back(); } } else { - for (size_t i = 0; i < count - list.size; i++) { - Node *nd = new Node; + size_t s = list.size; + for (size_t i = 0; i < count - s; i++) { + auto *nd = new typename List::Node; kassert(nd != nullptr); - insert_node_after(list.last, nd); + insert_node_after(list.last(), &nd->link); } } } @@ -417,26 +449,33 @@ class KLinkedList final { pop_back(); } } else { - for (size_t i = 0; i < count - list.size; i++) { - Node *nd = new Node{value}; + size_t s = list.size; + for (size_t i = 0; i < count - s; i++) { + auto *nd = new typename List::Node{value}; kassert(nd != nullptr); - insert_node_after(list.last, nd); + insert_node_after(list.last(), &nd->link); } } } void splice(const_iterator pos, KLinkedList &&other) { - Node *before = pos.node->prev; - Node *after = pos.node->next; - before->next = other.list.first; + //auto *current = pos.node; + auto *before = pos.node->prev; + auto *after = pos.node; //current == &list.link ? current : pos.node->next; + before->next = other.list.first(); before->next->prev = before; - after->prev = other.list.last; + after->prev = other.list.last(); after->prev->next = after; list.size += other.list.size; other.list.size = 0; - other.list.first = other.list.last = (Node *)&other.list; + other.list.link.prev = other.list.link.next = &other.list.link; + } + + void splice(const_iterator pos, KLinkedList &other) + { + splice(pos, std::move(other)); } void splice(const_iterator pos, KLinkedList &&other, const_iterator it) @@ -445,11 +484,17 @@ class KLinkedList final { insert_node_before(pos.node, it.node); } + void splice(const_iterator pos, KLinkedList &other, const_iterator it) + { + splice(pos, std::move(other), it); + } + void splice(const_iterator pos, KLinkedList &&other, const_iterator first, const_iterator last) { if (*this == other) { - Node *before = pos.node->prev; - Node *after = pos.node->next; + auto *current = pos.node; + auto *before = pos.node->prev; + auto *after = current == &list.link ? current : pos.node->next; before->next = first.node; before->next->prev = before; after->prev = last.node; @@ -466,6 +511,11 @@ class KLinkedList final { } } + void splice(const_iterator pos, KLinkedList &other, const_iterator first, const_iterator last) + { + splice(pos, std::move(other), first, last); + } + size_t remove(const T &value) { size_t n = 0; @@ -485,6 +535,7 @@ class KLinkedList final { size_t remove_if(UnaryPredicate p) { const_iterator next; + size_t n = 0; for (const_iterator it = cbegin(); it != cend(); ) { if (p(*it)) { it = erase(it); @@ -497,18 +548,18 @@ class KLinkedList final { } template - void merge(KLinkedList &other, Compare p) + void merge(KLinkedList &&other, Compare p) { - Node hd{}; - Node *cur = &hd; + typename List::Node::Link hd{}; + auto *cur = &hd; size_t n = 0; while (list.size > 0 && other.list.size > 0) { - if (p(list.first, other.list.first)) { - cur->next = list.first; - remove_node(list.first); + if (p(list.first()->data(), other.list.first()->data())) { + cur->next = list.first(); + remove_node(list.first()); } else { - cur->next = other.list.first; - other.remove_node(other.list.first); + cur->next = other.list.first(); + other.remove_node(other.list.first()); } cur->next->prev = cur; cur = cur->next; @@ -517,75 +568,77 @@ class KLinkedList final { // Steal the remaining elements if (list.size > 0) { - cur->next = list.first; - list.first->prev = cur; + cur->next = list.first(); + list.first()->prev = cur; + cur = list.last(); n += list.size; } else if (other.list.size > 0) { - cur->next = other.list.first; - other.list.first->prev = cur; + cur->next = other.list.first(); + other.list.first()->prev = cur; + cur = other.list.last(); n += other.list.size; } + // Reset the other list to put it in a valid state - other.list.first = other.list.last = (Node *)other.list; + other.list.link.prev = other.list.link.next = &other.list.link; other.list.size = 0; // Finally, normalize the result and assign it to this - list.first = hd.next; - list.last = cur; + list.link.next = hd.next; + list.link.prev = cur; list.size = n; - list.first->prev = list.last->next = (Node *)list; - } - - void merge(KLinkedList &other) - { - merge(other, std::less{}); - } - - template - void merge(KLinkedList &&other, Compare p) - { - KLinkedList &o = other; - merge(o, p); + list.first()->prev = list.last()->next = &list.link; } void merge(KLinkedList &&other) { - merge(other, std::less{}); + merge(other, std::less{}); + } + + template + void merge(KLinkedList &other, Compare p) + { + merge(std::move(other), p); + } + + void merge(KLinkedList &other) + { + merge(other, std::less{}); } void reverse() noexcept { - Node hd{}; - Node *cur = &hd; + typename List::Node::Link hd{}; + auto *cur = &hd; size_t n = 0; while (list.size > 0) { - cur->next = list.last; - remove_node(list.last); + cur->next = list.last(); + remove_node(list.last()); cur->next->prev = cur; n++; cur = cur->next; } - list.first = hd.next; - list.last = cur; + list.link.next = hd.next; + list.link.prev = cur; list.size = n; - list.first->prev = list.last->next = (Node *)list; + list.first()->prev = list.last()->next = &list.link; } template size_t unique(BinaryPredicate p) { - Node *nxt; + typename List::Node::Link *nxt; size_t n = 0; - for (Node *nd = list.first; nd != (Node *)list; nd = nxt) { + for (auto *nd = list.first(); nd != &list.link; nd = nxt) { nxt = nd->next; - for (Node *nd2 = nxt; nd2 != (Node *)list && p(nd->data, nd2->data); nd2 = nxt) { + for (auto *nd2 = nxt; nd2 != &list.link && p(nd->data(), nd2->data()); nd2 = nxt) { nxt = nd2->next; remove_node(nd2); - delete nd2; + delete &nd2->parent(); ++n; } } @@ -595,7 +648,7 @@ class KLinkedList final { size_t unique() { - return unique(std::equal_to); + return unique(std::equal_to{}); } // sort: a PITA to implement and not needed anyway @@ -612,22 +665,22 @@ class KLinkedList final { friend bool operator<(const KLinkedList &lhs, const KLinkedList &rhs) { - return std::lexicographical_compare(lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend(), std::less{}); + return std::lexicographical_compare(lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend(), std::less{}); } friend bool operator>(const KLinkedList &lhs, const KLinkedList &rhs) { - return std::lexicographical_compare(lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend(), std::greater{}); + return std::lexicographical_compare(lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend(), std::greater{}); } friend bool operator<=(const KLinkedList &lhs, const KLinkedList &rhs) { - return std::lexicographical_compare(lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend(), std::less_equal{}); + return std::lexicographical_compare(lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend(), std::less_equal{}); } friend bool operator>=(const KLinkedList &lhs, const KLinkedList &rhs) { - return std::lexicographical_compare(lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend(), std::greater_equal{}); + return std::lexicographical_compare(lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend(), std::greater_equal{}); } friend void swap(KLinkedList &lhs, KLinkedList &rhs) @@ -637,4 +690,7 @@ class KLinkedList final { }; +template +KLinkedList(InputIt b, InputIt e) -> KLinkedList::value_type>; + }