mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 02:32:36 +01:00
Implement lf_bunch<>
Simple concurrent container without erase support.
This commit is contained in:
parent
2e85b5ebaa
commit
7a32af7a57
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user