mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 02:32:36 +01:00
lf_fifo: fix UB and fix size()
Simplify internal counter to atomic<u64>. Make size() return correct difference between push and pop pointers.
This commit is contained in:
parent
833fbe015e
commit
7fcc49004d
@ -54,51 +54,46 @@ public:
|
|||||||
template<typename T, std::size_t N>
|
template<typename T, std::size_t N>
|
||||||
class lf_fifo : public lf_array<T, N>
|
class lf_fifo : public lf_array<T, N>
|
||||||
{
|
{
|
||||||
struct alignas(8) ctrl_t
|
// LSB 32-bit: push, MSB 32-bit: pop
|
||||||
{
|
atomic_t<u64> m_ctrl{};
|
||||||
u32 push;
|
|
||||||
u32 pop;
|
|
||||||
};
|
|
||||||
|
|
||||||
atomic_t<ctrl_t> m_ctrl{};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr lf_fifo() = default;
|
constexpr lf_fifo() = default;
|
||||||
|
|
||||||
// Get current "push" position
|
// Get number of elements in the queue
|
||||||
u32 size() const
|
u32 size() const
|
||||||
{
|
{
|
||||||
return m_ctrl.load().push;
|
const u64 ctrl = m_ctrl.load();
|
||||||
|
return static_cast<u32>(ctrl - (ctrl >> 32));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Acquire the place for one or more elements.
|
// Acquire the place for one or more elements.
|
||||||
u32 push_begin(u32 count = 1)
|
u32 push_begin(u32 count = 1)
|
||||||
{
|
{
|
||||||
return std::bit_cast<atomic_t<u64>*>(&m_ctrl)->fetch_add(count); // Hack
|
return m_ctrl.fetch_add(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get current "pop" position
|
// Get current "pop" position
|
||||||
u32 peek() const
|
u32 peek() const
|
||||||
{
|
{
|
||||||
return m_ctrl.load().pop;
|
return static_cast<u32>(m_ctrl >> 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Acknowledge processed element, return number of the next one.
|
// Acknowledge processed element, return number of the next one.
|
||||||
// Perform clear if possible, zero is returned in this case.
|
// Perform clear if possible, zero is returned in this case.
|
||||||
u32 pop_end(u32 count = 1)
|
u32 pop_end(u32 count = 1)
|
||||||
{
|
{
|
||||||
return m_ctrl.atomic_op([&](ctrl_t& ctrl)
|
return m_ctrl.atomic_op([&](u64& ctrl)
|
||||||
{
|
{
|
||||||
ctrl.pop += count;
|
ctrl += u64{count} << 32;
|
||||||
|
|
||||||
if (ctrl.pop == ctrl.push)
|
if (ctrl >> 32 == static_cast<u32>(ctrl))
|
||||||
{
|
{
|
||||||
// Clean if possible
|
// Clean if possible
|
||||||
ctrl.push = 0;
|
ctrl = 0;
|
||||||
ctrl.pop = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ctrl.pop;
|
return static_cast<u32>(ctrl >> 32);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user