mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-18 20:52:10 +01:00
[dxvk] Introduce lock-free list
This commit is contained in:
parent
c9750f6657
commit
a4fe43462c
130
src/util/sync/sync_list.h
Normal file
130
src/util/sync/sync_list.h
Normal file
@ -0,0 +1,130 @@
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
|
||||
namespace dxvk::sync {
|
||||
|
||||
/**
|
||||
* \brief Lock-free single-linked list
|
||||
*/
|
||||
template<typename T>
|
||||
class List {
|
||||
|
||||
struct Entry {
|
||||
Entry(T&& data_)
|
||||
: data(std::move(data_)), next(nullptr) { }
|
||||
Entry(const T& data_)
|
||||
: data(data_), next(nullptr) { }
|
||||
template<typename... Args>
|
||||
Entry(Args... args)
|
||||
: data(std::forward<Args>(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<typename... Args>
|
||||
Iterator emplace(Args... args) {
|
||||
return insertEntry(new Entry(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::atomic<Entry*> 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;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user