Files
panopainter/engine/util.h

110 lines
2.9 KiB
C++

#pragma once
uint16_t constexpr const_hash(const char* input)
{
return *input ?
static_cast<uint16_t>(*input) + 33 * const_hash(input + 1) :
5381;
}
bool point_in_rect(const glm::vec2& point, const glm::vec4& rect);
glm::vec4 rect_intersection(glm::vec4 a, glm::vec4 b);
glm::vec4 rect_union(glm::vec4 a, glm::vec4 b);
bool segments_intersect(const glm::vec2& p0a, const glm::vec2& p0b,
const glm::vec2& p1a, const glm::vec2& p1b, glm::vec2& out_pt);
glm::vec4 rand_color();
glm::vec3 convert_hsv2rgb(const glm::vec3 c);
glm::vec3 convert_rgb2hsv(const glm::vec3 c);
void check_OpenGLError(const char* stmt, const char* fname, int line);
template<typename T, int N> struct cbuffer
{
T m_vec[N];
int m_capacity;
int m_count;
int m_index;
cbuffer()
{
m_capacity = N;
m_index = 0;
m_count = 0;
}
T& head()
{
return m_index == 0 ? m_vec[m_count - 1] : m_vec[m_index - 1];
}
void add(const T& v)
{
m_vec[m_index] = v;
m_index = (m_index + 1) % m_capacity;
m_count = m_count < m_capacity ? m_count + 1 : m_count;
}
int count() const
{
return m_count;
}
template<typename T2 = T> T2 average() const
{
T2 tot{};
if (m_count == 0)
return tot;
for (int i = 0; i < m_count; i++)
tot += m_vec[i];
return tot / (float)m_count;
}
};
NS_START
template<typename T, int Max = 0>
class BlockingQueue
{
std::deque<T> q;
std::condition_variable post_cv;
std::condition_variable get_cv;
mutable std::mutex mutex;
public:
volatile bool unlocked = false;
BlockingQueue() = default;
BlockingQueue(const BlockingQueue& other) = delete;
BlockingQueue& operator=(const BlockingQueue& other) = delete;
BlockingQueue(BlockingQueue&& other) : q(std::move(q)) { }
BlockingQueue& operator=(BlockingQueue&& other) { q = std::move(q); return *this; }
void Post(T&& pkt)
{
std::unique_lock<std::mutex> lock(mutex);
if (Max > 0)
{
post_cv.wait(lock, [&]() { return unlocked | (q.size() < Max); });
if (q.size() >= Max) return;
}
q.push_back(std::forward<T>(pkt));
get_cv.notify_one();
}
T Get()
{
static T emptyT{};
std::unique_lock<std::mutex> lock(mutex);
get_cv.wait(lock, [&]() { return unlocked | (q.size() > 0); });
if (q.empty())
return std::move(emptyT);
T tmp = std::move(q.front());
q.pop_front();
if (Max > 0) post_cv.notify_all();
return std::move(tmp);
}
void UnlockGetters()
{
unlocked = true;
get_cv.notify_all();
if (Max > 0) post_cv.notify_all();
}
int Size() const
{
std::lock_guard<std::mutex> lock(mutex);
return (int)q.size();
}
};
NS_END