1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-25 12:12:50 +01:00

Implement lf_bunch<>

Simple concurrent container without erase support.
This commit is contained in:
Nekotekina 2019-10-25 15:15:45 +03:00
parent 2e85b5ebaa
commit 7a32af7a57

View File

@ -163,6 +163,9 @@ class lf_queue_item final
template <typename U>
friend class lf_queue;
template <typename U>
friend class lf_bunch;
constexpr lf_queue_item() = default;
template <typename... Args>
@ -195,6 +198,9 @@ class lf_queue_iterator
template <typename U>
friend class lf_queue_slice;
template <typename U>
friend class lf_bunch;
public:
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)
template <typename T>
class lf_value final