satdump/src-core/common/resizeable_buffer.h

78 lines
1.7 KiB
C
Raw Normal View History

#pragma once
#include <cstring>
2022-02-25 16:29:35 +01:00
#include <mutex>
/*
Simple resizeable buffer.
2022-02-24 19:33:58 +01:00
This was made for usecases where manual management is fine,
and std::vector too slow... Such as all the image processing.
The aim is not to automate memory management, but rather to be a
wrapper around reszing, without any performance impact compared
to a native array.
Operator overloading is utilized not to complexify things. This
should still be usable like a normal array.
*/
template <typename T>
class ResizeableBuffer
{
private:
size_t d_size;
2022-02-24 19:33:58 +01:00
size_t d_width;
size_t d_headroom;
public:
2022-02-25 16:29:35 +01:00
std::mutex buffer_lock;
T *buf;
bool destroyed = true;
2022-02-25 16:29:35 +01:00
public:
2022-02-24 19:33:58 +01:00
ResizeableBuffer() { d_size = 0; }
2022-02-25 16:29:35 +01:00
~ResizeableBuffer() { destroy(); }
2022-02-25 16:29:35 +01:00
void destroy()
{
if (!destroyed)
delete[] buf;
destroyed = true;
}
2022-02-24 19:33:58 +01:00
size_t size() { return d_size; }
2022-02-24 19:33:58 +01:00
T &operator[](int i)
{
2022-02-24 19:33:58 +01:00
// check(i / d_width);
return buf[i];
}
2022-02-24 19:33:58 +01:00
void create(size_t width, size_t headroom = 1000)
{
2022-02-24 19:33:58 +01:00
d_width = width;
d_headroom = headroom;
d_size = d_width * d_headroom;
buf = new T[d_size];
destroyed = false;
}
void resize(size_t newSize)
{
2022-02-25 16:29:35 +01:00
buffer_lock.lock();
if (newSize > d_size)
{
T *newBuffer = new T[newSize];
std::memcpy(newBuffer, buf, d_size * sizeof(T));
delete[] buf;
buf = newBuffer;
d_size = newSize;
}
2022-02-25 16:29:35 +01:00
buffer_lock.unlock();
}
2022-02-24 19:33:58 +01:00
void check(size_t lines)
{
2022-02-24 19:33:58 +01:00
if (lines * d_width >= d_size) // Check for 1 extra!
resize(d_width * (lines + d_headroom));
}
};