mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-05 22:41:25 +12:00
Implement lf_bunch<>
Simple concurrent container without erase support.
This commit is contained in:
parent
2e85b5ebaa
commit
7a32af7a57
1 changed files with 81 additions and 0 deletions
|
@ -163,6 +163,9 @@ class lf_queue_item final
|
||||||
template <typename U>
|
template <typename U>
|
||||||
friend class lf_queue;
|
friend class lf_queue;
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
friend class lf_bunch;
|
||||||
|
|
||||||
constexpr lf_queue_item() = default;
|
constexpr lf_queue_item() = default;
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
|
@ -195,6 +198,9 @@ class lf_queue_iterator
|
||||||
template <typename U>
|
template <typename U>
|
||||||
friend class lf_queue_slice;
|
friend class lf_queue_slice;
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
friend class lf_bunch;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr lf_queue_iterator() = default;
|
constexpr lf_queue_iterator() = default;
|
||||||
|
|
||||||
|
@ -456,6 +462,81 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Concurrent linked list, elements remain until destroyed.
|
||||||
|
template <typename T>
|
||||||
|
class lf_bunch final
|
||||||
|
{
|
||||||
|
atomic_t<lf_queue_item<T>*> m_head{nullptr};
|
||||||
|
|
||||||
|
public:
|
||||||
|
constexpr lf_bunch() noexcept = default;
|
||||||
|
|
||||||
|
~lf_bunch()
|
||||||
|
{
|
||||||
|
delete m_head.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add unconditionally
|
||||||
|
template <typename... Args>
|
||||||
|
T* push(Args&&... args) noexcept
|
||||||
|
{
|
||||||
|
auto _old = m_head.load();
|
||||||
|
auto item = new lf_queue_item<T>(_old, std::forward<Args>(args)...);
|
||||||
|
|
||||||
|
while (!m_head.compare_exchange(_old, item))
|
||||||
|
{
|
||||||
|
item->m_link = _old;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &item->m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add if pred(item, all_items) is true for all existing items
|
||||||
|
template <typename F, typename... Args>
|
||||||
|
T* push_if(F pred, Args&&... args) noexcept
|
||||||
|
{
|
||||||
|
auto _old = m_head.load();
|
||||||
|
auto _chk = _old;
|
||||||
|
auto item = new lf_queue_item<T>(_old, std::forward<Args>(args)...);
|
||||||
|
|
||||||
|
_chk = nullptr;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
item->m_link = _old;
|
||||||
|
|
||||||
|
// Check all items in the queue
|
||||||
|
for (auto ptr = _old; ptr != _chk; ptr = ptr->m_link)
|
||||||
|
{
|
||||||
|
if (!pred(item->m_data, ptr->m_data))
|
||||||
|
{
|
||||||
|
item->m_link = nullptr;
|
||||||
|
delete item;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set to not check already checked items
|
||||||
|
_chk = _old;
|
||||||
|
}
|
||||||
|
while (!m_head.compare_exchange(_old, item));
|
||||||
|
|
||||||
|
return &item->m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
lf_queue_iterator<T> begin() const
|
||||||
|
{
|
||||||
|
lf_queue_iterator<T> result;
|
||||||
|
result.m_ptr = m_head.load();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
lf_queue_iterator<T> end() const
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Assignable lock-free thread-safe value of any type (memory-inefficient)
|
// Assignable lock-free thread-safe value of any type (memory-inefficient)
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class lf_value final
|
class lf_value final
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue