59 lines
1.3 KiB
C++
59 lines
1.3 KiB
C++
#pragma once
|
|
#include <concepts>
|
|
namespace zstd {
|
|
template<size_t T>
|
|
struct static_buffer {
|
|
char data[T];
|
|
};
|
|
template<std::move_constructible T, size_t T_capacity = 1>
|
|
class channel_static {
|
|
static_assert(T_capacity != 0);
|
|
protected:
|
|
int m_tail;
|
|
int m_head;
|
|
static_buffer<sizeof(T)> m_buf[T_capacity];
|
|
std::mutex m_mtx;
|
|
std::condition_variable m_cv;
|
|
public:
|
|
~channel_static() {
|
|
reset();
|
|
}
|
|
channel_static() : m_tail(0), m_head(0), m_buf() {}
|
|
int head() {
|
|
return m_head;
|
|
}
|
|
int tail() {
|
|
return m_tail;
|
|
}
|
|
int count() {
|
|
return m_head - m_tail;
|
|
}
|
|
void reset() {
|
|
for (int i = m_tail; i < m_head; i++) {
|
|
std::destroy_at((T*)(m_buf + m_tail % T_capacity));
|
|
}
|
|
m_tail = 0;
|
|
m_head = 0;
|
|
}
|
|
template<typename... Args>
|
|
void release(Args... args) {
|
|
std::unique_lock<std::mutex> lck(m_mtx);
|
|
while (m_head >= m_tail + T_capacity) {
|
|
m_cv.wait(lck);
|
|
}
|
|
std::construct_at((T*)(m_buf + m_head % T_capacity), std::forward<Args>(args)...);
|
|
if (m_head++ == m_tail)
|
|
m_cv.notify_one();
|
|
};
|
|
T acquire() {
|
|
std::unique_lock<std::mutex> lck(m_mtx);
|
|
while (m_tail >= m_head) {
|
|
m_cv.wait(lck);
|
|
}
|
|
int tail = m_tail % T_capacity;
|
|
if (m_tail++ == m_head - T_capacity)
|
|
m_cv.notify_one();
|
|
return std::move(*(T*)(m_buf + tail));
|
|
};
|
|
};
|
|
} |