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);
}
constchar* 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:
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.