10#include <condition_variable>
22 template <
class T,
size_t CAPACITY>
26#pragma warning(suppress:26495)
38 std::tuple<T*, size_t>
back()
40 std::unique_lock<std::mutex> lk(m_mutex);
42 m_head_moved.wait(lk, [&]{
return m_quit || space();});
43 if (m_quit) _Unlikely_
44 return {
nullptr, 0 };
46 size_t tail = wrap(m_head + m_size);
47 return { &m_data[tail], m_head <= tail ? CAPACITY - tail : m_head - tail };
55 void push(_In_
size_t size)
58 const std::lock_guard<std::mutex> lg(m_mutex);
60 size_t tail = wrap(m_head + m_size);
61 assert(size <= (m_head <= tail ? CAPACITY - tail : m_head - tail));
65 m_tail_moved.notify_one();
75 std::unique_lock<std::mutex> lk(m_mutex);
77 m_tail_moved.wait(lk, [&]{
return m_quit || !empty();});
78 if (m_quit && empty()) _Unlikely_
79 return {
nullptr, 0 };
81 size_t tail = wrap(m_head + m_size);
82 return { &m_data[m_head], m_head < tail ? m_size : CAPACITY - m_head };
90 void pop(_In_
size_t size)
93 const std::lock_guard<std::mutex> lg(m_mutex);
95 size_t tail = wrap(m_head + m_size);
96 assert(size <= (m_head < tail ? m_size : CAPACITY - m_head));
98 m_head = wrap(m_head + size);
101 m_head_moved.notify_one();
110 const std::lock_guard<std::mutex> lg(m_mutex);
113 m_head_moved.notify_one();
114 m_tail_moved.notify_one();
122 std::unique_lock<std::mutex> lk(m_mutex);
123 m_head_moved.wait(lk, [&]{
return m_quit || empty();});
127 inline size_t wrap(_In_
size_t idx)
const
130 return idx % CAPACITY;
133 inline size_t space()
const
135 return CAPACITY - m_size;
138 inline bool empty()
const
145 std::condition_variable m_head_moved, m_tail_moved;
146 size_t m_head, m_size;
Ring buffer.
Definition ring.hpp:24
void quit()
Cancells waiting sender and receiver.
Definition ring.hpp:107
std::tuple< T *, size_t > back()
Allocates the data after the ring tail. Use push() after the allocated data is populated.
Definition ring.hpp:38
void pop(size_t size)
Notifies the sender the data was consumed.
Definition ring.hpp:90
void sync()
Waits until the ring is flush.
Definition ring.hpp:120
std::tuple< T *, size_t > front()
Peeks the data at the ring head. Use pop() after the data was consumed.
Definition ring.hpp:73
void push(size_t size)
Notifies the receiver the data was populated.
Definition ring.hpp:55