I wrote this simple class that provides buffering for general output operation:
template <typename T>
class WriteBuffer {
typedef void (&flush_t)(const T* values, const size_t size);
public:
WriteBuffer(size_t size, flush_t flush) : flush_(flush) {
v_.reserve(size);
}
~WriteBuffer() { flush(); }
void flush() {
if (v_.size() > 0) {
flush_(&v_[0], v_.size());
v_.clear();
}
}
void write(const T value) {
if (v_.size() == v_.capacity())
flush();
v_.push_back(value);
}
private:
vector<T> v_;
flush_t flush_;
};
(Error checking is omitted for simplicity.) The following example program:
void writeInt(const int* values, const size_t size) {
cout << "Writing buffer of size " << size << ": " << endl;
for (size_t i = 0; i < size; ++i)
cout << values[i] << ", ";
cout << endl;
}
int main(int argc, char* argv[]) {
WriteBuffer<int> buffer(5, writeInt);
for (size_t i = 0; i < 18; ++i)
buffer.write(i);
return 0;
}
then generates the following output:
Writing buffer of size 5: 0, 1, 2, 3, 4, Writing buffer of size 5: 5, 6, 7, 8, 9, Writing buffer of size 5: 10, 11, 12, 13, 14, Writing buffer of size 3: 15, 16, 17,
Is there any standard/better solution of this problem, e.g. some STL container / BOOST class with similar capabilities? Thanks!
Additional question: Would you prefer using function object instead of function reference flush_t
?
I would like to use such buffering for any type T
and any flush
operation provided by the client (not only characters and output streams). For example:
template <typename T>
void write(const T* values, const size_t size) {
...
H5Dwrite(..., values);
...
}
WriteBuffer<unsigned long> buffer(8192, write<unsigned long>);
to write data into HDF5 dataset. (Not solving here HDF5 data types.)
The standard solution is to subclass std::streambuf
, which was exactly designed for your task. There is some boost
magic to ease implementation.