From a4fe43462ce6be0be4dbcd2242c99eba046e209c Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sat, 19 Feb 2022 15:14:25 +0100 Subject: [PATCH] [dxvk] Introduce lock-free list --- src/util/sync/sync_list.h | 130 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 src/util/sync/sync_list.h diff --git a/src/util/sync/sync_list.h b/src/util/sync/sync_list.h new file mode 100644 index 00000000..9fb50d85 --- /dev/null +++ b/src/util/sync/sync_list.h @@ -0,0 +1,130 @@ +#pragma once + +#include + +namespace dxvk::sync { + + /** + * \brief Lock-free single-linked list + */ + template + class List { + + struct Entry { + Entry(T&& data_) + : data(std::move(data_)), next(nullptr) { } + Entry(const T& data_) + : data(data_), next(nullptr) { } + template + Entry(Args... args) + : data(std::forward(args)...), next(nullptr) { } + + T data; + Entry* next; + }; + + public: + + class Iterator { + + public: + + using iterator_category = std::forward_iterator_tag; + using difference_type = std::ptrdiff_t; + using value_type = T; + using pointer = T*; + using reference = T&; + + Iterator() + : m_entry(nullptr) { } + + Iterator(Entry* e) + : m_entry(e) { } + + reference operator * () const { + return m_entry->data; + } + + pointer operator -> () const { + return &m_entry->data; + } + + Iterator& operator ++ () { + m_entry = m_entry->next; + return *this; + } + + Iterator operator ++ (int) { + Iterator tmp(m_entry); + m_entry = m_entry->next; + return tmp; + } + + bool operator == (const Iterator& other) const { return m_entry == other.m_entry; } + bool operator != (const Iterator& other) const { return m_entry != other.m_entry; } + + private: + + Entry* m_entry; + + }; + + using iterator = Iterator; + + List() + : m_head(nullptr) { } + List(List&& other) + : m_head(other.m_head.exchange(nullptr)) { } + + List& operator = (List&& other) { + freeList(m_head.exchange(other.m_head.exchange(nullptr))); + return *this; + } + + ~List() { + freeList(m_head.load()); + } + + auto begin() const { return Iterator(m_head); } + auto end() const { return Iterator(nullptr); } + + Iterator insert(const T& data) { + return insertEntry(new Entry(data)); + } + + Iterator insert(T&& data) { + return insertEntry(new Entry(std::move(data))); + } + + template + Iterator emplace(Args... args) { + return insertEntry(new Entry(std::forward(args)...)); + } + + private: + + std::atomic m_head; + + Iterator insertEntry(Entry* e) { + Entry* next = m_head.load(std::memory_order_acquire); + + do { + e->next = next; + } while (!m_head.compare_exchange_weak(next, e, + std::memory_order_release, + std::memory_order_acquire)); + + return Iterator(e); + } + + void freeList(Entry* e) { + while (e) { + Entry* next = e->next;; + delete e; + e = next; + } + } + + }; + +}