psemek/libs/io/source/synchronized.cpp

60 lines
1.5 KiB
C++

#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;
}
}