1#ifndef BYTEME_BUFFERED_WRITER_HPP
2#define BYTEME_BUFFERED_WRITER_HPP
10#include <condition_variable>
40template<
typename Type_,
class WriterPo
inter_ = std::unique_ptr<Writer> >
47 if (buffer_size == 0) {
48 throw std::runtime_error(
"buffer size must be positive");
66 virtual void flush_async() = 0;
68 virtual void flush_sync(
const Type_*, std::size_t) = 0;
70 std::vector<Type_>& get_buffer() {
78 std::vector<Type_> my_buffer;
79 std::size_t my_current = 0;
83 unsigned long long my_overall = 0;
84 bool my_overall_failed =
false;
93 return safe_report_position(my_overall, my_current, my_overall_failed);
104 my_buffer[my_current] = input;
107 const auto buffer_size = my_buffer.size();
108 if (my_current == buffer_size) {
111 safe_update_position(my_overall, buffer_size, my_overall_failed);
123 const auto buffer_size = my_buffer.size();
126 const std::size_t remaining = buffer_size - my_current;
128 std::copy_n(input,
number, my_buffer.data() + my_current);
133 std::copy_n(input, remaining, my_buffer.data() + my_current);
139 safe_update_position(my_overall, buffer_size, my_overall_failed);
144 flush_sync(my_buffer.data(), buffer_size);
145 safe_update_position(my_overall, buffer_size, my_overall_failed);
148 while (
number >= buffer_size) {
149 flush_sync(input, buffer_size);
150 safe_update_position(my_overall, buffer_size, my_overall_failed);
151 input += buffer_size;
156 std::copy_n(input,
number, my_buffer.data());
167 write(
reinterpret_cast<const Type_*
>(
string), std::char_traits<char>::length(
string));
176 void write(
const std::string&
string) {
177 write(
reinterpret_cast<const Type_*
>(
string.c_str()),
string.size());
187 flush_sync(my_buffer.data(), my_current);
188 safe_update_position(my_overall, my_current, my_overall_failed);
211template<
typename Type_,
class Po
inter_ = std::unique_ptr<Writer> >
240 auto& buffer = this->get_buffer();
241 my_writer->write(
reinterpret_cast<unsigned char*
>(buffer.data()), buffer.size());
244 void flush_sync(
const Type_* ptr, std::size_t num) {
245 my_writer->write(
reinterpret_cast<const unsigned char*
>(ptr), num);
269template<
typename Type_,
class Po
inter_ = std::unique_ptr<Writer> >
280 my_writer(std::move(writer)),
281 my_buffer_worker(
sanisizer::cast<I<decltype(my_buffer_worker.size())> >(buffer_size))
283 my_thread = std::thread([&]() { thread_loop(); });
292 std::unique_lock lck(my_mut);
294 my_ready_input =
true;
305 std::vector<Type_> my_buffer_worker;
306 std::size_t my_to_write = 0;
309 std::thread my_thread;
310 std::exception_ptr my_thread_err =
nullptr;
312 std::condition_variable my_cv;
314 bool my_ready_input =
false, my_ready_output =
false;
315 bool my_worker_active =
false;
316 bool my_kill =
false;
320 std::unique_lock lck(my_mut);
321 my_cv.wait(lck, [&]() {
return my_ready_input; });
322 my_ready_input =
false;
329 my_writer->write(
reinterpret_cast<const unsigned char*
>(my_buffer_worker.data()), my_to_write);
331 my_thread_err = std::current_exception();
334 my_ready_output =
true;
345 auto& buffer = this->get_buffer();
346 const auto num = buffer.size();
348 if (my_worker_active) {
351 std::unique_lock lck(my_mut);
352 my_cv.wait(lck, [&]() {
return my_ready_output; });
353 my_ready_output =
false;
356 std::rethrow_exception(my_thread_err);
359 buffer.swap(my_buffer_worker);
362 my_ready_input =
true;
368 std::unique_lock lck(my_mut);
369 buffer.swap(my_buffer_worker);
372 my_ready_input =
true;
375 my_worker_active =
true;
379 void flush_sync(
const Type_* ptr, std::size_t num) {
380 if (my_worker_active) {
389 std::unique_lock lck(my_mut);
390 my_cv.wait(lck, [&]() {
return my_ready_output; });
391 my_ready_output =
false;
393 std::rethrow_exception(my_thread_err);
396 my_writer->write(
reinterpret_cast<const unsigned char*
>(ptr), num);
397 my_worker_active =
false;
401 my_writer->write(
reinterpret_cast<const unsigned char*
>(ptr), num);
Buffered wrapper around a Writer.
Definition BufferedWriter.hpp:41
unsigned long long number() const
Definition BufferedWriter.hpp:92
void flush()
Definition BufferedWriter.hpp:186
void write(const Type_ *input, std::size_t number)
Definition BufferedWriter.hpp:122
void write(const char *string)
Definition BufferedWriter.hpp:166
void write(Type_ input)
Definition BufferedWriter.hpp:103
void write(const std::string &string)
Definition BufferedWriter.hpp:176
Parallelized buffering to wrap a Writer.
Definition BufferedWriter.hpp:270
ParallelBufferedWriter(Pointer_ writer, std::size_t buffer_size)
Definition BufferedWriter.hpp:278
void finish()
Definition BufferedWriter.hpp:409
Serial buffering to wrap a Writer.
Definition BufferedWriter.hpp:212
void finish()
Definition BufferedWriter.hpp:252
SerialBufferedWriter(Pointer_ writer, std::size_t buffer_size)
Definition BufferedWriter.hpp:220
Simple byte readers and writers.
Definition BufferedReader.hpp:25
constexpr Dest_ cast(Value_ x)