9#include <condition_variable>
14#pragma GCC diagnostic push
15#pragma GCC diagnostic ignored "-Wunknown-pragmas"
26 template <
class T,
size_t N_cap>
30#pragma warning(suppress:26495)
42 std::tuple<T*, size_t>
back()
44 std::unique_lock<std::mutex> lk(m_mutex);
46 m_head_moved.wait(lk, [&]{
return m_quit || space();});
47 if (m_quit) _Unlikely_
48 return {
nullptr, 0 };
50 size_t tail = wrap(m_head + m_size);
51 return { &m_data[tail], m_head <= tail ? N_cap - tail : m_head - tail };
59 void push(_In_
size_t size)
62 const std::lock_guard<std::mutex> lg(m_mutex);
64 size_t tail = wrap(m_head + m_size);
65 _Assume_(size <= (m_head <= tail ? N_cap - tail : m_head - tail));
69 m_tail_moved.notify_one();
79 std::unique_lock<std::mutex> lk(m_mutex);
81 m_tail_moved.wait(lk, [&]{
return m_quit || !empty();});
82 if (m_quit && empty()) _Unlikely_
83 return {
nullptr, 0 };
85 size_t tail = wrap(m_head + m_size);
86 return { &m_data[m_head], m_head < tail ? m_size : N_cap - m_head };
94 void pop(_In_
size_t size)
97 const std::lock_guard<std::mutex> lg(m_mutex);
99 size_t tail = wrap(m_head + m_size);
100 _Assume_(size <= (m_head < tail ? m_size : N_cap - m_head));
102 m_head = wrap(m_head + size);
105 m_head_moved.notify_one();
114 const std::lock_guard<std::mutex> lg(m_mutex);
117 m_head_moved.notify_one();
118 m_tail_moved.notify_one();
126 std::unique_lock<std::mutex> lk(m_mutex);
127 m_head_moved.wait(lk, [&]{
return m_quit || empty();});
131 size_t wrap(_In_
size_t idx)
const
139 return N_cap - m_size;
149 std::condition_variable m_head_moved, m_tail_moved;
150 size_t m_head, m_size;
157#pragma GCC diagnostic pop
Ring buffer.
Definition ring.hpp:28
void pop(size_t size)
Notifies the sender the data was consumed.
Definition ring.hpp:94
std::tuple< T *, size_t > back()
Allocates the data after the ring tail. Use push() after the allocated data is populated.
Definition ring.hpp:42
void quit()
Cancells waiting sender and receiver.
Definition ring.hpp:111
std::tuple< T *, size_t > front()
Peeks the data at the ring head. Use pop() after the data was consumed.
Definition ring.hpp:77
void push(size_t size)
Notifies the receiver the data was populated.
Definition ring.hpp:59
void sync()
Waits until the ring is flush.
Definition ring.hpp:124