From 4078c9a07d9bec3a6d6c55bb6b5238215921f58a Mon Sep 17 00:00:00 2001 From: TuxSH Date: Thu, 1 Nov 2018 21:59:06 +0100 Subject: [PATCH] Implement KLinkedList; untested --- mesosphere/config/common.mk | 2 +- .../include/mesosphere/core/KLinkedList.hpp | 640 ++++++++++++++++++ mesosphere/source/my_libc.c | 2 +- 3 files changed, 642 insertions(+), 2 deletions(-) create mode 100644 mesosphere/include/mesosphere/core/KLinkedList.hpp diff --git a/mesosphere/config/common.mk b/mesosphere/config/common.mk index 00e9f8c3d..58e73b3b8 100644 --- a/mesosphere/config/common.mk +++ b/mesosphere/config/common.mk @@ -2,7 +2,7 @@ COMMON_DEFINES := -DBOOST_DISABLE_ASSERTS COMMON_SOURCES_DIRS := source/core source/interfaces source/interrupts source/kresources\ source/processes source/threading source COMMON_SETTING := -fPIE -g -nostdlib -COMMON_CFLAGS := -Wall -Werror -O2 -ffunction-sections -fdata-sections -fno-strict-aliasing -fwrapv\ +COMMON_CFLAGS := -Wall -Werror -Os -ffunction-sections -fdata-sections -fno-strict-aliasing -fwrapv\ -fno-asynchronous-unwind-tables -fno-unwind-tables -fno-stack-protector COMMON_CXXFLAGS := -fno-rtti -fno-exceptions -std=gnu++17 COMMON_ASFLAGS := diff --git a/mesosphere/include/mesosphere/core/KLinkedList.hpp b/mesosphere/include/mesosphere/core/KLinkedList.hpp new file mode 100644 index 000000000..32d288842 --- /dev/null +++ b/mesosphere/include/mesosphere/core/KLinkedList.hpp @@ -0,0 +1,640 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace mesosphere +{ + +template +class KLinkedList final { + private: + + struct List { + Node *last; + Node *first; + 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) + { + // if pos is last & list is empty, ->next writes to first, etc. + pos->next->prev = nd; + nd->prev = pos; + nd->next = pos->next; + pos->next = nd; + ++list.size; + } + + void insert_node_before(Node *pos, Node *nd) + { + pos->prev->next = nd; + nd->prev = pos->prev; + nd->next = pos; + pos->prev = nd; + ++list.size; + } + + void remove_node(Node *nd) + { + nd->prev->next = nd->next; + nd->next->prev = nd->prev; + --list.size; + } + public: + + template + class Iterator { + public: + using iterator_category = std::bidirectional_iterator_tag; + using value_type = typename KLinkedList::value_type; + using difference_type = typename KLinkedList::difference_type; + using pointer = typename std::conditional< + isConst, + typename KLinkedList::const_pointer, + typename KLinkedList::pointer + >::type; + using reference = typename std::conditional< + isConst, + typename KLinkedList::const_reference, + typename KLinkedList::reference + >::type; + + bool operator==(const Iterator &other) const + { + return node == other.node; + } + + bool operator!=(const Iterator &other) const + { + return !(*this == other); + } + + reference operator*() + { + return node->data; + } + + pointer operator->() + { + return &node->data; + } + + Iterator &operator++() + { + node = node->next; + return *this; + } + + Iterator &operator--() { + node = node->prev; + return *this; + } + + Iterator &operator++(int) { + const Iterator v{*this}; + ++(*this); + return v; + } + + Iterator &operator--(int) { + const Iterator v{*this}; + --(*this); + return v; + } + + // allow implicit const->non-const + Iterator(const Iterator &other) : node{other.node} {} + + friend class Iterator; + Iterator() = default; + + private: + friend class KLinkedList; + + KLinkedList::Node *node; + + explicit Iterator(KLinkedList::Node *node) : node{node} {} + }; + + using pointer = T *; + using const_pointer = const T *; + using void_pointer = void *; + using const_void_ptr = const void *; + using value_type = T; + using size_type = size_t; + using difference_type = ptrdiff_t; + using iterator = Iterator; + using const_iterator = Iterator; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + KLinkedList() : list{(Node *)&list, (Node *)&list} {}; + explicit KLinkedList(size_t count, const T &value) : KLinkedList() + { + for (size_t i = 0; i < count; i++) { + Node *nd = new Node{value}; + kassert(nd != nullptr); + insert_node_after(list.last, nd); + } + } + + explicit KLinkedList(size_t count) : KLinkedList() + { + for (size_t i = 0; i < count; i++) { + Node *nd = new Node; + kassert(nd != nullptr); + insert_node_after(list.last, nd); + } + } + + template>> + explicit KLinkedList(InputIt first, InputIt last) : KLinkedList() + { + for (InputIt it = first; it != last; ++it) { + Node *nd = new Node{*it}; + kassert(nd != nullptr); + insert_node_after(list.last, nd); + } + } + + void swap(KLinkedList &other) noexcept + { + using std::swap; // Enable ADL + swap(list.first, other.list.first); + swap(list.last, other.list.last); + swap(list.size, other.list.size); + } + + KLinkedList(KLinkedList &&other) noexcept : KLinkedList() + { + swap(other); + } + KLinkedList(std::initializer_list ilist) : KLinkedList(ilist.begin(), ilist.end()) {} + + void clear() noexcept + { + Node *nxt; + for (Node nd = list.first; nd != (Node *)&list; nd = nxt) { + nxt = nd->next; + delete nd; + } + list.size = 0; + } + + ~KLinkedList() + { + clear(); + } + + KLinkedList &operator=(KLinkedList other) + { + swap(*this, other); + return *this; + } + + KLinkedList &operator=(std::initializer_list ilist) + { + KLinkedList tmp{ilist}; + swap(*this, tmp); + return *this; + } + + void assign(size_t count, const T &value) + { + KLinkedList tmp{count, value}; + swap(*this, tmp); + } + + template>> + void assign(InputIt first, InputIt last) + { + KLinkedList tmp{first, last}; + swap(*this, tmp); + } + + void assign(std::initializer_list ilist) + { + KLinkedList tmp{ilist}; + swap(*this, tmp); + } + + 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; } + + const_iterator cbegin() const noexcept { return const_iterator{list.first}; } + const_iterator cend() const noexcept { return const_iterator{(Node *)&list}; } + + 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}; } + + 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 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}; } + + KLinkedList(const KLinkedList &other) : KLinkedList(other.cbegin(), other.cend()) {} + + constexpr size_t size() const noexcept { return list.size; } + constexpr bool empty() const noexcept { return list.size == 0; } + + iterator insert(const_iterator pos, const T &value) + { + Node *nd = new Node{value}; + kassert(nd != nullptr); + insert_node_after(pos.node, nd); + } + + iterator insert(const_iterator pos, T &&value) + { + Node *nd = new Node{value}; + kassert(nd != nullptr); + insert_node_before(pos.node, nd); + return iterator{nd}; + } + + iterator insert(const_iterator pos, size_t count, const T &value) + { + iterator ret = pos; + for (size_t i = 0; i < count; i++) { + ret = insert(ret, value); + } + return ret; + } + + template>> + 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; + for(InputIt it = first; it != last; ++it) { + Node *nd = new Node{value}; + kassert(nd != nullptr); + insert_node_after(p, nd); + p = nd; + f = f == nullptr ? nd : f; + } + + return iterator{f}; + } + + template + iterator emplace(const_iterator pos, Args &&...args) + { + Node *nd = new Node{std::forward(args)...}; + kassert(nd != nullptr); + insert_node_before(pos.node, nd); + return iterator{nd}; + } + + iterator erase(const_iterator pos) + { + iterator ret{pos->next}; + remove_node(pos.node); + delete pos.node; + return ret; + } + + iterator erase(const_iterator first, const_iterator last) + { + const_iterator next; + for (const_iterator it = first; it != last; it = next) { + next = erase(it); + } + return iterator{next.node}; + } + + void push_back(const T &value) + { + Node *nd = new Node{value}; + kassert(nd != nullptr); + insert_node_after(list.last, nd); + } + + void push_back(T &&value) + { + Node *nd = new Node{value}; + kassert(nd != nullptr); + insert_node_after(list.last, nd); + } + + template< class... Args> + T &emplace_back(Args&&... args) + { + Node *nd = new Node{std::forward(args)...}; + kassert(nd != nullptr); + insert_node_after(list.last, nd); + return nd->data; + } + + void pop_back() + { + remove_node(list.last); + delete list.last; + } + + void push_front(const T &value) + { + Node *nd = new Node{value}; + kassert(nd != nullptr); + insert_node_before(list.first, nd); + } + + void push_front(T &&value) + { + Node *nd = new Node{value}; + kassert(nd != nullptr); + insert_node_before(list.first, nd); + } + + template< class... Args> + T &emplace_front(Args&&... args) + { + Node *nd = new Node{std::forward(args)...}; + kassert(nd != nullptr); + insert_node_before(list.first, nd); + return nd->data; + } + + void pop_front() + { + remove_node(list.first); + } + + void resize(size_t count) + { + if (count < list.size) { + while (count < list.size) { + pop_back(); + } + } else { + for (size_t i = 0; i < count - list.size; i++) { + Node *nd = new Node; + kassert(nd != nullptr); + insert_node_after(list.last, nd); + } + } + } + + void resize(size_t count, const T &value) + { + if (count < list.size) { + while (count < list.size) { + pop_back(); + } + } else { + for (size_t i = 0; i < count - list.size; i++) { + Node *nd = new Node{value}; + kassert(nd != nullptr); + insert_node_after(list.last, nd); + } + } + } + + void splice(const_iterator pos, KLinkedList &&other) + { + Node *before = pos.node->prev; + Node *after = pos.node->next; + before->next = other.list.first; + before->next->prev = before; + 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; + } + + void splice(const_iterator pos, KLinkedList &&other, const_iterator it) + { + other.remove_node(it.node); + insert_node_before(pos.node, it.node); + } + + 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; + before->next = first.node; + before->next->prev = before; + after->prev = last.node; + after->prev->next = after; + } else { + // Note: the first, last version can't be O(1) because std::distance is O(n)... + const_iterator next; + for (const_iterator it = first; it != last; it = next) { + next = it; + ++next; + splice(pos, other, it); + ++pos; + } + } + } + + size_t remove(const T &value) + { + size_t n = 0; + const_iterator next; + for (const_iterator it = cbegin(); it != cend(); ) { + if (*it == value) { + it = erase(it); + ++n; + } else { + ++it; + } + } + return n; + } + + template + size_t remove_if(UnaryPredicate p) + { + const_iterator next; + for (const_iterator it = cbegin(); it != cend(); ) { + if (p(*it)) { + it = erase(it); + ++n; + } else { + ++it; + } + } + return n; + } + + template + void merge(KLinkedList &other, Compare p) + { + Node hd{}; + Node *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); + } else { + cur->next = other.list.first; + other.remove_node(other.list.first); + } + cur->next->prev = cur; + cur = cur->next; + n++; + } + + // Steal the remaining elements + if (list.size > 0) { + cur->next = list.first; + list.first->prev = cur; + n += list.size; + } else if (other.list.size > 0) { + cur->next = other.list.first; + other.list.first->prev = cur; + 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.size = 0; + + // Finally, normalize the result and assign it to this + list.first = hd.next; + list.last = 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); + } + + void merge(KLinkedList &&other) + { + merge(other, std::less{}); + } + + void reverse() noexcept + { + Node hd{}; + Node *cur = &hd; + size_t n = 0; + + while (list.size > 0) { + cur->next = list.last; + remove_node(list.last); + cur->next->prev = cur; + n++; + cur = cur->next; + } + + list.first = hd.next; + list.last = cur; + list.size = n; + list.first->prev = list.last->next = (Node *)list; + } + + + template + size_t unique(BinaryPredicate p) + { + Node *nxt; + size_t n = 0; + for (Node *nd = list.first; nd != (Node *)list; nd = nxt) { + nxt = nd->next; + for (Node *nd2 = nxt; nd2 != (Node *)list && p(nd->data, nd2->data); nd2 = nxt) { + nxt = nd2->next; + remove_node(nd2); + delete nd2; + ++n; + } + } + + return n; + } + + size_t unique() + { + return unique(std::equal_to); + } + + // sort: a PITA to implement and not needed anyway + + friend bool operator==(const KLinkedList &lhs, const KLinkedList &rhs) + { + return std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin()); + } + + friend bool operator!=(const KLinkedList &lhs, const KLinkedList &rhs) + { + return !(lhs == rhs); + } + + friend bool operator<(const KLinkedList &lhs, const KLinkedList &rhs) + { + 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{}); + } + + friend bool operator<=(const KLinkedList &lhs, const KLinkedList &rhs) + { + 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{}); + } + + friend void swap(KLinkedList &lhs, KLinkedList &rhs) + { + lhs.swap(rhs); + } + +}; + +} diff --git a/mesosphere/source/my_libc.c b/mesosphere/source/my_libc.c index 38497c1ee..f4d12c296 100644 --- a/mesosphere/source/my_libc.c +++ b/mesosphere/source/my_libc.c @@ -828,7 +828,7 @@ strcpy (char *dst0, #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) char *s = dst0; - while (*dst0++ = *src0++) + while ((*dst0++ = *src0++)) ; return s;