While trying some mutex-locked print function, I got an idea like this:
class MyWriteStream
{
public:
MyWriteStream(std::ostream &stream) : stream_(std::move(stream)) {}
void write(const char *str, const size_t size)
{
std::lock_guard<std::mutex> lock(mutex_);
stream_.write(str, size);
}
friend MyWriteStream & operator << (MyWriteStream &out, const char *c);
private:
std::ostream &&stream_;
std::mutex mutex_;
};
MyWriteStream & operator << (MyWriteStream &out, const char *c)
{
out.write(c, strlen(c) * sizeof(char));
return out;
}
And while calling, I did something like this:
MyWriteStream stream(std::cout);
auto blah = [&stream](const char *s) {
stream << s << "\n";
};
std::vector<std::thread> threads;
for (auto i = 0; i<10; ++i) {
std::string str = "blah : " + std::to_string(i);
threads.push_back(std::thread(blah, str.c_str()));
}
for (auto &thread : threads) {
thread.join();
}
std::cout << "hello" << std::endl; // Still Works
It appears I didn't manage to move std::cout
, as next line still works. What has happened? Could std::move
also bind reference? Also, if I were to make it into usable class, was this a bad idea?
[Edit] It does look like bad idea, as there is issue with synchronization. I'm trying to understand same. Any hints are most welcome. I guess, I need to study r-value references in more depth.