Reputation: 13160
Having multiple processes, all writing on the same output stream (e.g. with std::cout
), is there a way to lock the stream so that, when a process starts writing his own message, it can do it till the end (e.g. with std::endl
)?
I need a portable way of doing it.
Upvotes: 1
Views: 457
Reputation: 3370
It's not clear if it would fit the parameters of your situation, but you could potentially funnel all data to a separate worker process that aggregates the data (with its own internal locking) before dumping them to stdout.
Upvotes: 2
Reputation: 70382
If you are on a UNIX like OS, then you may be able to mimic the behavior you want with a stringstream
adapter. This may not be the best way to accomplish it, but the idea is to trigger a single write
call whenever std::endl
is encountered.
// Assume fd is in blocking mode
class fdostream : public std::ostringstream {
typedef std::ostream & (*manip_t) (std::ostream &);
struct fdbuf : public std::stringbuf {
int fd_;
fdbuf (int fd) : fd_(fd) {}
int sync () {
int r = ::write(fd_, str().data(), str().size());
str(std::string());
return (r > 0) ? 0 : -1;
}
} buf_;
std::ostream & os () { return *this; }
public:
fdostream (int fd) : buf_(fd) { os().rdbuf(&buf_); }
};
fdostream my_cout(1);
my_cout << "Hello," << " world!" << std::endl;
This should achieve the effect of synchronized writes, at the cost of buffering input into a stringstream
and then clearing the internal string
after each flush.
For greater portability, you could modify the code to use fwrite
, and specify unbuffered writes with setvbuf
. But, the atomicity of fwrite
would depend on the C implementation of the library function.
Upvotes: 1
Reputation: 18228
You are out of luck. You will have to use whatever your taget OS provides. This means using global/system-wide mutexes or lockf()
like functions. You could use some 3rd party library to satisfy the portability requirement, like Boost.Interprocess.
Upvotes: 2