Hi,
I'm trying to implement an atomic ostream class.
It streams the data into an internal ostringstream buffer and writes the buffer as a single string to cout.
So I don't get messed up output when outputting from several threads (since a single streaming operation is atomic as far as I can remember).
This is what it should "look" like:
1 2
|
AtomicCout aCout;
aCout << 1 << "2" << '3' << someClassThatOverloadsTheStreamOperator;
|
What I accomplished so far is that I can fill the internal ostringstream and print it during the destructor being executed.
I tried to define an operator void() for the class and thought it might get executed if the class ends up being in an void context. But it seams that this operator is never invoked.
This is was also works but is not as "beautiful"
1 2 3 4
|
{
AtomicCout aCout;
aCout << 1 << "2" << '3' << someClassThatOverloadsTheStreamOperator;
}
|
1 2
|
AtomicCout aCout;
aCout << 1 << "2" << specialClassThatIssuesAtomicCoutToFlushItsBuffers;
|
I also tried it with a temporary but the output is messed up if the first object to stream is a const char*:
|
AtomicCout() << "1" << 2;
|
I stepped through the program and found out that << "1" calls the function
_Myt& __CLR_OR_THIS_CALL operator<<(const void *_Val)
(using Visual Studio 8.0) so
const char*
is converted to a
const void*
and therefore prints the address of the pointer I think.
But this doesn't happen if I don't use a temporary object.
And this also doesn't happen if I first stream in something else, like here:
|
AtomicCout() << 1 << "2";
|
This is the complete code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
#pragma once
#include <sstream>
#include <iostream>
class AtomicWrite : public std::ostream
{
public:
AtomicWrite();
~AtomicWrite();
operator void();
private:
std::ostringstream _os;
};
AtomicWrite::AtomicWrite()
: std::ostream(0)
, _os()
{
this->init(_os.rdbuf());
}
AtomicWrite::~AtomicWrite()
{
_os << '\n';
std::cout << _os.str();
}
AtomicWrite::operator void()
{
; // just a breakpoint that get's never triggered...
}
|
I tested it with this code:
1 2 3 4 5 6 7 8 9 10
|
AtomicWrite() << "0" << 1 << 2.0 << '3' << "4";
AtomicWrite() << 0 << "1" << 2.0 << '3' << "4";
{
AtomicWrite aw;
aw << "0" << 1 << 2.0 << '3' << "4";
}
{
AtomicWrite aw;
aw << 0 << "1" << 2.0 << '3' << "4";
}
|
this was the output:
1 2 3 4
|
0048D6141234
01234
01234
01234
|