2 changed files with 234 additions and 0 deletions
@ -0,0 +1,233 @@ |
|||||
|
// 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 KLinkedListNode : public boost::intrusive::list_base_hook<>, |
||||
|
public KSlabAllocated<KLinkedListNode> { |
||||
|
private: |
||||
|
void* m_item; |
||||
|
|
||||
|
public: |
||||
|
KLinkedListNode() : m_item(nullptr) {} |
||||
|
|
||||
|
constexpr void Initialize(void* it) { |
||||
|
m_item = it; |
||||
|
} |
||||
|
|
||||
|
constexpr void* GetItem() const { |
||||
|
return m_item; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
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 = typename std::conditional<Const, KLinkedList::const_pointer, |
||||
|
KLinkedList::pointer>::type; |
||||
|
using reference = typename std::conditional<Const, KLinkedList::const_reference, |
||||
|
KLinkedList::reference>::type; |
||||
|
|
||||
|
private: |
||||
|
BaseIterator m_base_it; |
||||
|
|
||||
|
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); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
public: |
||||
|
constexpr KLinkedList() : BaseList() {} |
||||
|
|
||||
|
~KLinkedList() { |
||||
|
// Erase all elements. |
||||
|
for (auto it = this->begin(); it != this->end(); it = this->erase(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(); |
||||
|
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(const iterator pos) { |
||||
|
KLinkedListNode* freed_node = std::addressof(*pos.m_base_it); |
||||
|
iterator ret = iterator(BaseList::erase(pos.m_base_it)); |
||||
|
KLinkedListNode::Free(freed_node); |
||||
|
|
||||
|
return ret; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
} // namespace Kernel |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue