Jump to content
  • Advertisement
Sign in to follow this  
Zeu5

std::cout syncronization in multithreading

This topic is 5223 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi all, I'm writing a multithreaded text application in Win32, C++ and STLport, using std::cout for text output. The output stream is not automatically synchronized and I get messy outputs like: Thread1 code: cout << "Hello" << endl; Thread2 code: cout << "World!" << endl; Output: HeWlorlld!o There is a simply way to make it synchronized? Thanks.

Share this post


Link to post
Share on other sites
Advertisement
Well, you could use a mutex to make sure only one thread is doing output at any time.
The api you're using to do threads should have some way to create mutexes.

Share this post


Link to post
Share on other sites
It's not exactly simple, in that it isn't transparent, but you could create a few simple little classes like so:


class c_Mutex
{
public:
c_Mutex();
~c_Mutex();
void Enter();
bool TryEnter();
void Leave();

protected:
CRITICAL_SECTION mCriticalSection;
};

class c_Mutex_Lock
{
public:
c_Mutex_Lock(c_Mutex* pMutex);
~c_Mutex_Lock();

protected:
c_Mutex* mpMutex;
};



c_Mutex::c_Mutex()
{
InitializeCriticalSection(&mCriticalSection);
}

c_Mutex::~c_Mutex()
{
DeleteCriticalSection(&mCriticalSection);
}

void c_Mutex::Enter()
{
EnterCriticalSection(&mCriticalSection);
}

bool c_Mutex::TryEnter()
{
return TryEnterCriticalSection(&mCriticalSection) != FALSE;
}

void c_Mutex::Leave()
{
LeaveCriticalSection(&mCriticalSection);
}



c_Mutex_Lock::c_Mutex_Lock(c_Mutex* pMutex)
{
mpMutex = pMutex;
if (mpMutex != NULL)
mpMutex->Enter();
}

c_Mutex_Lock::~c_Mutex_Lock()
{
if (mpMutex != NULL)
{
mpMutex->Leave();
}
}




Then you can create a global somewhere, call it something like gOutMutex. In your source code, when you want to print something out, put all the std::cout statements in an extra set of curly braces, and declare a c_Mutex_Lock object at th top:


c_Mutex gOutMutex;

int main()
{
//Start threads here...

{
c_Mutex_Lock OutLock(&gOutMutex);
std::cout << "Blah" << std::endl;
std::cout << "More Blah" << std::endl;
std::cout << "Final Blah" << std::endl;
}

return 0;
};



The c_Mutex_Lock object will lock the c_Mutex object on creation, and when it goes out of scope (at the end of the block), it will unlock the c_Mutex object. It is safe even against exceptions, since the c_Mutex_Object's destructor will be called then as well. It adds a few lines to every time you want to print stuff out, but it gets the job done.

Share this post


Link to post
Share on other sites
Also, I believe cout is internally synchronized, so you can just make sure you write to a single formatted string first, then put that string out to cout in one call.

Share this post


Link to post
Share on other sites
Quote:
Original post by Stoffel
Also, I believe cout is internally synchronized, so you can just make sure you write to a single formatted string first, then put that string out to cout in one call.
In my experience (with VC++'s implementation, using the multithreaded library) this is not the case. Somehow it manages to not only get characters from two different threads mixed together (even if each thread only uses a single << operator), but often seems to grab one character from each thread, alternating back and forth perfectly. Maybe other implementations handle this better...

Share this post


Link to post
Share on other sites
Thanks Agony, I like your solution. I was thinking something similar but you did it better :)

Oh, I forgot.. I'm using STLport with the _STLP_NO_OWN_IOSTREAMS option. This option disable the use of STLport iostreams and use wrappers around compiler's iostreams, in my case VC++. Maybe with STLport iostreams, cout is automatically synchronized.. I have to try..

Share this post


Link to post
Share on other sites
Ok it works! But I have to call cout.flush() in the destructor of c_Mutex_Lock too.
Thanks Agony.

Share this post


Link to post
Share on other sites
Make a Log class that hides this mess and then do what Stoffel said.

stringstream ss;
ss << "Log this";

logger->log(ss.str().c_str());

And the log function should lock and unlock the futex (fast-mutex, aka process-local mutx, which is a "CriticalSection" in Win32)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!