Synchronize stdout & stderr for logging

This commit is contained in:
Nikita Lisitsa 2023-08-06 18:44:35 +03:00
parent 85d7a0ca33
commit 04243db779
3 changed files with 83 additions and 2 deletions

View file

@ -0,0 +1,15 @@
#pragma once
#include <psemek/io/stream.hpp>
#include <vector>
namespace psemek::io
{
// Convert a set of output streams to a set of mutually
// synchronized streams: writing to any of the streams
// flushes all the other streams
std::vector<std::unique_ptr<ostream>> synchronized(std::vector<std::unique_ptr<ostream>> streams);
}

View file

@ -0,0 +1,60 @@
#include <psemek/io/synchronized.hpp>
namespace psemek::io
{
namespace
{
struct synchronized_stream_impl
: ostream
{
synchronized_stream_impl(std::shared_ptr<ostream> stream, std::vector<std::weak_ptr<ostream>> others)
: stream_(std::move(stream))
, others_(std::move(others))
{}
std::size_t write(char const * p, std::size_t size) override
{
for (auto const & ptr : others_)
if (auto stream = ptr.lock())
stream->flush();
return stream_->write(p, size);
}
void flush() override
{
stream_->flush();
}
private:
std::shared_ptr<ostream> stream_;
std::vector<std::weak_ptr<ostream>> others_;
};
}
// Convert a set of output streams to a set of mutually
// synchronized streams: writing to any of the streams
// flushes all the other streams
std::vector<std::unique_ptr<ostream>> synchronized(std::vector<std::unique_ptr<ostream>> streams)
{
std::vector<std::shared_ptr<ostream>> shared_streams(streams.size());
for (std::size_t i = 0; i < streams.size(); ++i)
shared_streams[i] = std::move(streams[i]);
std::vector<std::unique_ptr<ostream>> result;
for (std::size_t i = 0; i < streams.size(); ++i)
{
std::vector<std::weak_ptr<ostream>> others;
for (std::size_t j = 0; j < streams.size(); ++j)
if (i != j)
others.push_back(shared_streams[i]);
result.push_back(std::make_unique<synchronized_stream_impl>(shared_streams[i], std::move(others)));
}
return result;
}
}

View file

@ -6,6 +6,7 @@
#include <psemek/util/clock.hpp>
#include <psemek/util/pretty_print.hpp>
#include <psemek/log/log.hpp>
#include <psemek/io/synchronized.hpp>
#include <psemek/util/exception.hpp>
#undef main
@ -22,8 +23,13 @@ int main(int argc, char ** argv) try
log::level const stdio_log_level = log::level::debug;
#endif
log::add_sink(log::default_sink(io::std_out(), stdio_log_level, log::level::info));
log::add_sink(log::default_sink(io::std_err(), log::level::warning, log::level::error));
std::vector<std::unique_ptr<io::ostream>> synchronized_stdout_stderr;
synchronized_stdout_stderr.push_back(io::std_out());
synchronized_stdout_stderr.push_back(io::std_err());
synchronized_stdout_stderr = io::synchronized(std::move(synchronized_stdout_stderr));
log::add_sink(log::default_sink(std::move(synchronized_stdout_stderr[0]), stdio_log_level, log::level::info));
log::add_sink(log::default_sink(std::move(synchronized_stdout_stderr[1]), log::level::warning, log::level::error));
log::register_thread("main");
auto const factory = app::make_application_factory();