diff options
author | bunnei <bunneidev@gmail.com> | 2021-05-08 08:30:17 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-08 08:30:17 +0200 |
commit | faa067f175cbf5e916ed75776817f0046e6731c4 (patch) | |
tree | 8ab02a72a6e4d6578848c8da2c02af02684aeec7 /src/core/hle/kernel/k_linked_list.h | |
parent | Merge pull request #6287 from lioncash/ldr-copy (diff) | |
parent | hle: kernel: KPageTable: CanContain should not be constexpr. (diff) | |
download | yuzu-faa067f175cbf5e916ed75776817f0046e6731c4.tar yuzu-faa067f175cbf5e916ed75776817f0046e6731c4.tar.gz yuzu-faa067f175cbf5e916ed75776817f0046e6731c4.tar.bz2 yuzu-faa067f175cbf5e916ed75776817f0046e6731c4.tar.lz yuzu-faa067f175cbf5e916ed75776817f0046e6731c4.tar.xz yuzu-faa067f175cbf5e916ed75776817f0046e6731c4.tar.zst yuzu-faa067f175cbf5e916ed75776817f0046e6731c4.zip |
Diffstat (limited to 'src/core/hle/kernel/k_linked_list.h')
-rw-r--r-- | src/core/hle/kernel/k_linked_list.h | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/src/core/hle/kernel/k_linked_list.h b/src/core/hle/kernel/k_linked_list.h new file mode 100644 index 000000000..500f44685 --- /dev/null +++ b/src/core/hle/kernel/k_linked_list.h @@ -0,0 +1,238 @@ +// Copyright 2021 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <boost/intrusive/list.hpp> + +#include "common/assert.h" +#include "core/hle/kernel/slab_helpers.h" + +namespace Kernel { + +class KernelCore; + +class KLinkedListNode : public boost::intrusive::list_base_hook<>, + public KSlabAllocated<KLinkedListNode> { + +public: + KLinkedListNode() = default; + + void Initialize(void* it) { + m_item = it; + } + + void* GetItem() const { + return m_item; + } + +private: + void* m_item = nullptr; +}; + +template <typename T> +class KLinkedList : private boost::intrusive::list<KLinkedListNode> { +private: + using BaseList = boost::intrusive::list<KLinkedListNode>; + +public: + template <bool Const> + class Iterator; + + using value_type = T; + using size_type = size_t; + using difference_type = ptrdiff_t; + using pointer = value_type*; + using const_pointer = const value_type*; + using reference = value_type&; + using const_reference = const value_type&; + using iterator = Iterator<false>; + using const_iterator = Iterator<true>; + using reverse_iterator = std::reverse_iterator<iterator>; + using const_reverse_iterator = std::reverse_iterator<const_iterator>; + + template <bool Const> + class Iterator { + private: + using BaseIterator = BaseList::iterator; + friend class KLinkedList; + + public: + using iterator_category = std::bidirectional_iterator_tag; + using value_type = typename KLinkedList::value_type; + using difference_type = typename KLinkedList::difference_type; + using pointer = std::conditional_t<Const, KLinkedList::const_pointer, KLinkedList::pointer>; + using reference = + std::conditional_t<Const, KLinkedList::const_reference, KLinkedList::reference>; + + public: + explicit Iterator(BaseIterator it) : m_base_it(it) {} + + pointer GetItem() const { + return static_cast<pointer>(m_base_it->GetItem()); + } + + bool operator==(const Iterator& rhs) const { + return m_base_it == rhs.m_base_it; + } + + bool operator!=(const Iterator& rhs) const { + return !(*this == rhs); + } + + pointer operator->() const { + return this->GetItem(); + } + + reference operator*() const { + return *this->GetItem(); + } + + Iterator& operator++() { + ++m_base_it; + return *this; + } + + Iterator& operator--() { + --m_base_it; + return *this; + } + + Iterator operator++(int) { + const Iterator it{*this}; + ++(*this); + return it; + } + + Iterator operator--(int) { + const Iterator it{*this}; + --(*this); + return it; + } + + operator Iterator<true>() const { + return Iterator<true>(m_base_it); + } + + private: + BaseIterator m_base_it; + }; + +public: + constexpr KLinkedList(KernelCore& kernel_) : BaseList(), kernel{kernel_} {} + + ~KLinkedList() { + // Erase all elements. + for (auto it = this->begin(); it != this->end(); it = this->erase(kernel, it)) { + } + + // Ensure we succeeded. + ASSERT(this->empty()); + } + + // Iterator accessors. + iterator begin() { + return iterator(BaseList::begin()); + } + + const_iterator begin() const { + return const_iterator(BaseList::begin()); + } + + iterator end() { + return iterator(BaseList::end()); + } + + const_iterator end() const { + return const_iterator(BaseList::end()); + } + + const_iterator cbegin() const { + return this->begin(); + } + + const_iterator cend() const { + return this->end(); + } + + reverse_iterator rbegin() { + return reverse_iterator(this->end()); + } + + const_reverse_iterator rbegin() const { + return const_reverse_iterator(this->end()); + } + + reverse_iterator rend() { + return reverse_iterator(this->begin()); + } + + const_reverse_iterator rend() const { + return const_reverse_iterator(this->begin()); + } + + const_reverse_iterator crbegin() const { + return this->rbegin(); + } + + const_reverse_iterator crend() const { + return this->rend(); + } + + // Content management. + using BaseList::empty; + using BaseList::size; + + reference back() { + return *(--this->end()); + } + + const_reference back() const { + return *(--this->end()); + } + + reference front() { + return *this->begin(); + } + + const_reference front() const { + return *this->begin(); + } + + iterator insert(const_iterator pos, reference ref) { + KLinkedListNode* node = KLinkedListNode::Allocate(kernel); + ASSERT(node != nullptr); + node->Initialize(std::addressof(ref)); + return iterator(BaseList::insert(pos.m_base_it, *node)); + } + + void push_back(reference ref) { + this->insert(this->end(), ref); + } + + void push_front(reference ref) { + this->insert(this->begin(), ref); + } + + void pop_back() { + this->erase(--this->end()); + } + + void pop_front() { + this->erase(this->begin()); + } + + iterator erase(KernelCore& kernel, const iterator pos) { + KLinkedListNode* freed_node = std::addressof(*pos.m_base_it); + iterator ret = iterator(BaseList::erase(pos.m_base_it)); + KLinkedListNode::Free(kernel, freed_node); + + return ret; + } + +private: + KernelCore& kernel; +}; + +} // namespace Kernel |