Unlock mutex when returning

The back-end of my application executes a command with _popen and passes the output to the front-end.

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
void Loader::LoadBuffer(const std::string& arg)
{
	/*	Block until output mutex unlocked,
		lock mutex, write data, unlock		*/ 

	{
		std::lock_guard<std::mutex> lock(outputMutex);
		outputBuffer += arg;
	}

	// Tell front-end that a chunk of output is ready
	bufferLoaded = true;

	// Sleep until buffer is emptied by client
	while (bufferLoaded)
		Sleep(10);
}
const char* Loader::OffloadBuffer()
{
	/*	Block until output mutex unlocked,
		lock mutex, return data, unlock	*/

	std::unique_lock<std::mutex> lock(outputMutex);
	return outputBuffer.c_str();
}
void Loader::ClearBuffer()
{
	outputBuffer.clear();
	outputBuffer = "";
	bufferLoaded = false;
}


A new thread is spawned for the function that executes the command (which calls LoadBuffer()), and OffloadBuffer() is called from the main thread.

The front-end waits until bufferLoaded is set, then calls OffloadBuffer() and ClearBuffer().

First of all, in OffloadBuffer(), the data in outputBuffer is returned at the same time the unique_lock is destroyed (unlocking the mutex) - I'm not sure of the order of events here - is the caller accessing the data after the mutex is unlocked?

Second, I want to mark these functions noexcept, and the resource management objects can throw when they're being destroyed - if I put the contents of OffloadBuffer in a try block:

1
2
3
4
5
6
7
8
9
try
{
	std::unique_lock<std::mutex> lock(outputMutex);
	return outputBuffer.c_str();
}
catch (...)
{
	// ...
}


...will this catch an exception thrown when lock is destroyed?
I'm not sure of the order of events here - is the caller accessing the data after the mutex is unlocked?

You're returning a pointer. At the time the caller use the pointer to read the data the function has ended and the mutex has been unlocked.

Another concern is that you're reading and writing to bufferLoaded from both threads without any protection (unless it's an atomic).
Last edited on
Whoops you're right, thanks I'll make bufferLoaded atomic.

As for outputBuffer, I read that I shouldn't make a unique_lock a member, so I guess I have to lock the mutex at the beginning of OffloadBuffer(), and manually unlock at the end of ClearBuffer().

Also, apparently, I should be using scoped_lock instead of lock_guard? Going to try these changes when I get home, thanks.
Registered users can post here. Sign in or register to post.