Thread save access to cout?

H

Henryk

Ok, my question is a little system-related. C++ does not know anything
about threads, I know. But where else to ask?

Under linux with libstdc++.so.6 is writing to cout thread save or do I
need to make it thread safe by some kind of wrapper?

The impact to existing code should be minimal (at best a simple search
& replace).

Would something like this do:

inline std::eek:stream &Wrapper::cout() {
Lock lock(mutex);
return std::cout;
}

And then use it like this

Wrapper::cout() << "print something" << "print more" << std::endl;

How long does the scoped lock protect the access to std::cout? The
mutex is released within lock's destructor, which is called after the
return statement.

I tested it in an VM environment and it worked as far as I visually
checked the output. But does it work for sure?

Thanks for any insights!

Henryk
 
M

Michael Doubez

Ok, my question is a little system-related. C++ does not know anything
about threads, I know. But where else to ask?

Under linux with libstdc++.so.6 is writing to cout thread save or do I
need to make it thread safe by some kind of wrapper?

The impact to existing code should be minimal (at best a simple search
& replace).

Would something like this do:

inline std::eek:stream &Wrapper::cout() {
  Lock lock(mutex);
  return std::cout;

}

And then use it like this

Wrapper::cout() << "print something" << "print more" << std::endl;

How long does the scoped lock protect the access to std::cout?

It doesn't.

The
mutex is released within lock's destructor, which is called after the
return statement.

I tested it in an VM environment and it worked as far as I visually
checked the output. But does it work for sure?

The stream is locked only within the function, which is useless.

With a lock, the solution should be
{
Lock lock_cout;
std::cout<< ...;
std::cout<< ...;
} // unlock cout


With a wrapper: instantiate a temporary that stays lock and redefine
operato<< for it:
class locked_cout
{
public:
locked_cout():lock(locked_cout::mutex)
{ /* NOP */ }
private:
// Lock
Lock lock;
// program wide mutex
static mutex _mutex;
};

template<class T>
const locked_cout& operator<<(const locked_cout& lcout, const T& t)
{
std::cout<<t;
return lcout;
}

const locked_cout& operator<<(const locked_cout& lcout, std::ios_base
(*manip)( std::ios_base& ) )
{
std::cout<<manip;
return lcout;
}

const locked_cout& operator<<(const locked_cout& lcout, std::eek:stream&
(*manip)( std::eek:stream& ) )
{
std::cout<<manip;
return lcout;
}

And you can do:
locked_cout()<< ... ;
or
{
const locked_cout lcout;
lcout<<...;
lcout<<...:
}

Credit: IIRC I have first seen this solution from James Kanze.
 
M

Marcel Müller

Hi,
Under linux with libstdc++.so.6 is writing to cout thread save or do I
need to make it thread safe by some kind of wrapper?

most C++ runtime implementations are thread safe to some degree if you
use the platform specific compiler switch for multi-threading. However,
this won't help you in any way. See below.

Would something like this do:

inline std::eek:stream &Wrapper::cout() {
Lock lock(mutex);
return std::cout;
}

In no way.

You lock, then you create a reference to std::cout, then you unlock and
finally you dereference the reference and do your output.
Wrapper::cout() << "print something" << "print more" << std::endl;

How long does the scoped lock protect the access to std::cout? The
mutex is released within lock's destructor, which is called after the
return statement.
Exactly.

I tested it in an VM environment and it worked as far as I visually
checked the output. But does it work for sure?

It never worked and you did not need it.


You will never address the problem with a general wrapper. The first
question is: what is your unit of work? Is <<"print something" a unit of
work and <<"print more" another one and in between another thread might
do it's output. Or is the entire expression your unit of work? Of
course, for both purposes you might write a wrapper, but both
implementation will have significant drawbacks. In any case you need to
implement your own virtual output stream.

The first alternative obviously does not hit the nail on the head,
because one logical set of outputs might be intercepted by content from
other threads.
The second way blocks the entire output stream until your returned
wrapper instance goes out of scope. Depending on your application code
this may be after the statement (as intended) at some other point or
even never resulting in a deadlock. Furthermore you will always lock the
output while subexpressions of your statement are evaluated. So if you
call a function in your output statement that retrieves the output
information, then it is evaluated in synchronized context. Again, this
is obviously not what you want.

You won't come around to redesign your output statements in your
application if you want to provide reasonable thread-safety.


Marcel
 
H

Henryk

Hi,


most C++ runtime implementations are thread safe to some degree if you
use the platform specific compiler switch for multi-threading. However,
this won't help you in any way. See below.



In no way.

You lock, then you create a reference to std::cout, then you unlock and
finally you dereference the reference and do your output.


It never worked and you did not need it.

You will never address the problem with a general wrapper. The first
question is: what is your unit of work? Is <<"print something" a unit of
work and <<"print more" another one and in between another thread might
do it's output. Or is the entire expression your unit of work? Of
course, for both purposes you might write a wrapper, but both
implementation will have significant drawbacks. In any case you need to
implement your own virtual output stream.

The first alternative obviously does not hit the nail on the head,
because one logical set of outputs might be intercepted by content from
other threads.
The second way blocks the entire output stream until your returned
wrapper instance goes out of scope. Depending on your application code
this may be after the statement (as intended) at some other point or
even never resulting in a deadlock. Furthermore you will always lock the
output while subexpressions of your statement are evaluated. So if you
call a function in your output statement that retrieves the output
information, then it is evaluated in synchronized context. Again, this
is obviously not what you want.

You won't come around to redesign your output statements in your
application if you want to provide reasonable thread-safety.

Marcel

For this purpose one chain of outputs must not be interrupted. So cout
<< "first statement" << "second statement"; shall be one continuous
output. As far as I understand, this requirement is not fulfilled by
the other solution (from Michael Doubez). Correct? The wrapper
function would be called for every single element in this chain, thus
would not give protection in-between, right?

Your thoughts about locking the output during parameter evaluation is
true and may be an issue. Somehow the whole chain should be streamed
to a local stringstream first, and then written to the console at
once. The std::endl could possibly used as an end-of-uninterruptable
output (but not a single '\n').

Hmm, I have t rethink that problem carefully ....

The problem is that the existing project is big and a rework of every
single output statement is a lot of work. Otherwise, the convenience
of doing these chained outputs should still be possible.

Again, I have to rethink ...
 
H

Henryk

A side question:

class A {
T someMember;
Mutex theMutex;

const T &getMember() {
Lock lock(this->theMutex;
return this->someMember;
}
};


Is a call like this is thread-safe?

A a;
T aCopy = a.getMember(); // thread-safe copy-operation?

Is the destructor of lock inside A::getMember called AFTER the copy-
operation of A::someMember to aCopy?

I know, I can not store a reference like this with respect to thread
safety. That's clear.

const T &aCopy = a.getMember();

I'm just not sure right know and can not do some testing at the
moment.

Henryk

PS: The code shall run on an embedded system. I could just return an
object and not a reference in getMember to assure thread safety. But
this would result in an unnecessary copy operation, which is an issue
at that small processor.
 
M

Marcel Müller

Henryk said:
A side question:

class A {
T someMember;
Mutex theMutex;

const T &getMember() {
Lock lock(this->theMutex;
return this->someMember;
}
};


Is a call like this is thread-safe?

A a;
T aCopy = a.getMember(); // thread-safe copy-operation?

Is the destructor of lock inside A::getMember called AFTER the copy-
operation of A::someMember to aCopy?

No. The copy operation is done by the caller. This is past the sequence
point of the method call. If you want to force a copy to be taken in
synchronized context you have to make the return type of getMember a
value type rather than a reference.
const T getMember()

PS: The code shall run on an embedded system. I could just return an
object and not a reference in getMember to assure thread safety. But
this would result in an unnecessary copy operation, which is an issue
at that small processor.

One death you have to die. But if you have a reasonable optimizing
compiler, it might optimize this in some common cases.

I strongly recommend to switch to some common logging library. This will
address almost all of your problems.


Marcel
 
M

Marcel Müller

Your thoughts about locking the output during parameter evaluation is
true and may be an issue. Somehow the whole chain should be streamed
to a local stringstream first, and then written to the console at
once.
Exactly.

The std::endl could possibly used as an end-of-uninterruptable
output (but not a single '\n').

No. This might never come, again resulting in a deadlock. Furthermore
std:endl is a constant identical to '\n'. You can't distinguish them.

However, you could do some thread-static line buffering and forward the
entire message not before you get '\n'. This also avoids the problem
with the evaluation of function within synchronized context.
But you may still get mince when the message body contains '\n', and you
get no output at all until everything is terminated by '\n'.
Hmm, I have t rethink that problem carefully ....

The problem is that the existing project is big and a rework of every
single output statement is a lot of work. Otherwise, the convenience
of doing these chained outputs should still be possible.

Use an appropriate logging library.
However, you will never be able to deal automatically with statement
sequences like:
cout << "Message head";
for (whatever)
{ cout << "some item info";
}
cout << std::endl;


Furthermore you might think about trace levels. Note that populating the
stringstream with the required information might be much more expensive
than the output itself. So taking back the trace level by discarding
some messages might not give the intended performance boost. You hav to
check the trace level /before/ you start to evaluate the message body.
This implies that the evaluation of the message must not have any side
effects, otherwise the application will behave differently depending on
the trace level.


Marcel
 
H

Henryk

No. This might never come, again resulting in a deadlock. Furthermore
std:endl is a constant identical to '\n'. You can't distinguish them.

However, you could do some thread-static line buffering and forward the
entire message not before you get '\n'. This also avoids the problem
with the evaluation of function within synchronized context.
But you may still get mince when the message body contains '\n', and you
get no output at all until everything is terminated by '\n'.



Use an appropriate logging library.
However, you will never be able to deal automatically with statement
sequences like:
   cout << "Message head";
   for (whatever)
   { cout << "some item info";
   }
   cout << std::endl;

Furthermore you might think about trace levels. Note that populating the
stringstream with the required information might be much more expensive
than the output itself. So taking back the trace level by discarding
some messages might not give the intended performance boost. You hav to
check the trace level /before/ you start to evaluate the message body.
This implies that the evaluation of the message must not have any side
effects, otherwise the application will behave differently depending on
the trace level.

Yes, I#m aware of the issue of unnecessarily doing all the type-to-
string conversion if the output is suppressed by a certain log-level.
We have to optimize that ... later ;o)

I remember another project, where a log function similar to fprintf/
printf was used. The advantage was, that the parameters were passed as-
is and then, inside the log function, the log-level was checked BEFORE
the actual work was done with vprintf. Pretty neat, but sooo C
style. ;o)

Henryk
 
J

John H.

is writing to cout thread save or do I
need to make it thread safe by some kind of wrapper?

Here is a simple solution, although it may require a lot of work to
install into your source code because it requires putting a ) at the
end of each print segement:

#define COUT_LOCK(x) {std::stringstream cout;\
x\
Lock lock(mutex);\
std::cout << cout.str();}

int main()
{
COUT_LOCK(cout << "Hello" << " world" << endl;)

COUT_LOCK(
cout << "Starting:";
for(int i = 0; i<10; i++)
{
cout << i;
}
cout << "done." << endl;)

return 0;
}

If your threading library has a concept of a thread id, something like
this is a little more complex, but easier to install into existing
software (actual thread safety needs to be filled in):

#include <iostream>
#include <sstream>
#include <map>

bool mutex = false;

class Lock
{
public:
Lock(bool & mutex) :
mutex(mutex)
{
while(mutex)
{
// wait
}
mutex = true;
}
~Lock()
{
mutex = false;
}
private:
bool & mutex;
};


typedef unsigned long pthread_t;
pthread_t pthread_self()
{
return 1ul;
}




namespace Threaded
{

class Endl
{
};
Endl endl;

class Print
{
public:
Print & operator<<(Endl)
{
if(buffers.find(pthread_self()) == buffers.end())
{
buffers.insert(std::pair<pthread_t, std::stringstream
*>(pthread_self(), new std::stringstream));
}
buffers[pthread_self()]->flush();
Lock lock(mutex);
std::cout << buffers[pthread_self()]->str() << std::endl;
buffers[pthread_self()]->seekg(std::stringstream::beg);
buffers[pthread_self()]->seekp(std::stringstream::beg);
return *this;
}

template <class T>
Print & operator<<(T const & t)
{
if(buffers.find(pthread_self()) == buffers.end())
{
buffers.insert(std::pair<pthread_t, std::stringstream
*>(pthread_self(), new std::stringstream));
}
*buffers[pthread_self()] << t;
return *this;
}

private:
static std::map<pthread_t, std::stringstream* > buffers;
};
std::map<pthread_t, std::stringstream *> Print::buffers;
Print cout;

};


using Threaded::cout;
using Threaded::endl;


char getSpace()
{
cout << "In getSpace" << endl;
return ' ';
}


int main()
{
cout << "Hello" << getSpace() << "world." << endl;

cout << "Starting:";
for(int i = 0; i<10; i++)
{
cout << i;
}
cout << "done." << endl;

return 0;
}
 
A

AnonMail2005

Ok, my question is a little system-related. C++ does not know anything
about threads, I know. But where else to ask?

Under linux with libstdc++.so.6 is writing to cout thread save or do I
need to make it thread safe by some kind of wrapper?

The impact to existing code should be minimal (at best a simple search
& replace).

Would something like this do:

inline std::eek:stream &Wrapper::cout() {
  Lock lock(mutex);
  return std::cout;

}

And then use it like this

Wrapper::cout() << "print something" << "print more" << std::endl;

How long does the scoped lock protect the access to std::cout? The
mutex is released within lock's destructor, which is called after the
return statement.

I tested it in an VM environment and it worked as far as I visually
checked the output. But does it work for sure?

Thanks for any insights!

Henryk

What we do is to separate the message builder from the class/function
that does the actual output. This way, the class that does the output
is trivial - it only outputs a string inside a function that is
protected by a lock.

Here's some psuedo code that implements a message builder. The key
point is that it implements the stream operator, and it's destructor
does the actual output by using some other mechanism to produce thread
safe output. If you don't like the operation in the destructor, then
just put it inside a member function.

// message builder
class LogMessage
{
public:
// default construct
LogMessage()
{}

// constructor taking a context
LogMessage(const char * context)
{
m_ss << context << ": ";
}

// constructor taking a context
LogMessage(const std::string & s)
{
m_ss << context << ": ";
}

// destructor - output the message to logger
~LogMessage()
{
logIt(m_ss.str());
}

// stream operator
template <class T>
LogMessage & operator<<(const T & t)
{
m_ss << t;
return *this;
}

private:
m_ostringstream m_ss;
};


//
//Use it like this somewhere else:
//

// build a message, it gets logged when the class destructs at the
semicolon
LogMessage("demo") << "this is a log message: " << 10;


// In some other file - the actual class (singleton) or function that
// does thread safe logging

// thread safe access to log stream
LogIt(const std::string & s)
{
// do lock here
std::cout << s << std::endl;
}

HTH
 
M

Marcel Müller

Henryk said:
I remember another project, where a log function similar to fprintf/
printf was used. The advantage was, that the parameters were passed as-
is and then, inside the log function, the log-level was checked BEFORE
the actual work was done with vprintf. Pretty neat, but sooo C
style. ;o)

Feel free to implement your own ostream with deferred execution. But
keep in mind that you can only defer something if it is evaluated in on
of your method calls. If the programmer concatenates something and
passes it as argument, then you have no influence.
Because of this conditional compiled macros are still used for logging
libraries. This gives you a compile time option to turn some code paths off.

If you need a runtime switch, you have either prepend all logging
statments with something like
if (loglevel(3)) ...
or you have to use lambda expressions. But the latter is like using a
sledgehammer to crack a nut.
I prefer the first. Whether to use macros or not is up to yours.


Marcel
 
M

Marcel Müller

LR said:

you are right, I forgot about the flush. But still you must do something
to prevent deadlocks. The solution with a thread static string stream
that only forwards its content on flush might be sufficient.

But I dislike solutions like these, because you have no performant
options to switch logging levels. OK, you might use different streams
for different severities. Some of them might turn everything in a no-op.
But you have to virtualize the entire ostream API to avoid unnecessary
conversions.


Marcel
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top