C++/Cli synchronizing threads writing to file - multithreading

I am trying to synchronize threads writing data to a text file in a class by using Monitor, but in my code it seems that the else statement is never evaluated, is this the correct use of monitor for thread synchronization?
void Bank::updatefile()
{
Thread^ current = Thread::CurrentThread;
bool open = false;
current->Sleep(1000);
while (!open)
{
if (Monitor::TryEnter(current))
{
String^ fileName = "accountdata.txt";
StreamWriter^ sw = gcnew StreamWriter(fileName);
for (int x = 0; x < 19; x++)
sw->WriteLine(accountData[x]);
sw->Close();
Monitor::Pulse;
Monitor::Exit(current);
current->Sleep(500);
open = true;
}
else
{
Monitor::Wait(current);
current->Sleep(500);
}
}
}

You're passing an object to Monitor::TryEnter that is specific to the thread in which it is executing (i.e. Thread^ current = Thread::CurrentThread;). No other threads are using the same object (they're using the one for their own thread). So there's never a collision or locking conflict.
Try creating some generic object that's shared among the threads, something higher up in the Bank class. Then use that for your TryEnter call.

Your use of Monitor is partially correct. The object you're using for locking is not correct.
Monitor
Monitor::Pulse is unnecessary here. Just Exit the monitor, and the next thread will be able to grab the lock.
Monitor::Wait is incorrect here: Wait is supposed to be used when the thread has the object already locked. Here, you have the object not locked yet.
In general, Pulse and Wait are rarely used. For locking for exclusive access to a shared resource, Enter, TryEnter, and Exit are all you need.
Here's how your use of Monitor should be written:
Object^ lockObj = ...;
bool done = false;
while(!done)
{
if(Monitor::TryEnter(lockObj, 500)) // wait 500 millis for the lock.
{
try
{
// do work
done = true;
}
finally
{
Monitor::Exit(lockObj);
}
}
else
{
// Check some other exit condition?
}
}
or if the else is empty, you can simplify it like this:
Object^ lockObj = ...;
Monitor::Enter(lockObj); // Wait forever for the lock.
try
{
// do work
}
finally
{
Monitor::Exit(lockObj);
}
There is a class that Microsoft provides that makes this all easier: msclr::lock. This class, used without the ^, makes use of the destructor to release the lock, without a try-finally block.
#include <msclr\lock.h>
bool done = false;
while(!done)
{
msclr::lock lock(lockObj, lock_later);
if (lock.try_acquire(500)) // wait 500 millis for the lock to be available.
{
// Do work
done = true;
}
} // <-- Monitor::Exit is called by lock class when it goes out of scope.
{
msclr::lock lock(lockObj); // wait forever for the lock to be available.
// Do work
} // <-- Monitor::Exit is called by lock class when it goes out of scope.
The object to lock on
Thread::CurrentThread is going to return a different object on each thread. Therefore, each thread attempts to lock on a different object, and that's why all of them succeed. Instead, have one object, created before you spawn your threads, that is used for locking.
Also, instead of opening & closing the file on each thread, it would be more efficient to open it once, before the threads are spawned, and then just use that one StreamWriter from each of the threads. This also gives you a obvious object to lock on: You can pass the StreamWriter itself to Monitor::Enter or msclr::lock.

Related

Worker thread suspend / resume implementation

In my attempt to add suspend / resume functionality to my Worker [thread] class, I've happened upon an issue that I cannot explain. (C++1y / VS2015)
The issue looks like a deadlock, however I cannot seem to reproduce it once a debugger is attached and a breakpoint is set before a certain point (see #1) - so it looks like it's a timing issue.
The fix that I could find (#2) doesn't make a lot of sense to me because it requires to hold on to a mutex longer and where client code might attempt to acquire other mutexes, which I understand to actually increase the chance of a deadlock.
But it does fix the issue.
The Worker loop:
Job* job;
while (true)
{
{
std::unique_lock<std::mutex> lock(m_jobsMutex);
m_workSemaphore.Wait(lock);
if (m_jobs.empty() && m_finishing)
{
break;
}
// Take the next job
ASSERT(!m_jobs.empty());
job = m_jobs.front();
m_jobs.pop_front();
}
bool done = false;
bool wasSuspended = false;
do
{
// #2
{ // Removing this extra scoping seemingly fixes the issue BUT
// incurs us holding on to m_suspendMutex while the job is Process()ing,
// which might 1, be lengthy, 2, acquire other locks.
std::unique_lock<std::mutex> lock(m_suspendMutex);
if (m_isSuspended && !wasSuspended)
{
job->Suspend();
}
wasSuspended = m_isSuspended;
m_suspendCv.wait(lock, [this] {
return !m_isSuspended;
});
if (wasSuspended && !m_isSuspended)
{
job->Resume();
}
wasSuspended = m_isSuspended;
}
done = job->Process();
}
while (!done);
}
Suspend / Resume is just:
void Worker::Suspend()
{
std::unique_lock<std::mutex> lock(m_suspendMutex);
ASSERT(!m_isSuspended);
m_isSuspended = true;
}
void Worker::Resume()
{
{
std::unique_lock<std::mutex> lock(m_suspendMutex);
ASSERT(m_isSuspended);
m_isSuspended = false;
}
m_suspendCv.notify_one(); // notify_all() doesn't work either.
}
The (Visual Studio) test:
struct Job: Worker::Job
{
int durationMs = 25;
int chunks = 40;
int executed = 0;
bool Process()
{
auto now = std::chrono::system_clock::now();
auto until = now + std::chrono::milliseconds(durationMs);
while (std::chrono::system_clock::now() < until)
{ /* busy, busy */
}
++executed;
return executed < chunks;
}
void Suspend() { /* nothing here */ }
void Resume() { /* nothing here */ }
};
auto worker = std::make_unique<Worker>();
Job j;
worker->Enqueue(j);
std::this_thread::sleep_for(std::chrono::milliseconds(j.durationMs)); // Wait at least one chunk.
worker->Suspend();
Assert::IsTrue(j.executed < j.chunks); // We've suspended before we finished.
const int testExec = j.executed;
std::this_thread::sleep_for(std::chrono::milliseconds(j.durationMs * 4));
Assert::IsTrue(j.executed == testExec); // We haven't moved on.
// #1
worker->Resume(); // Breaking before this call means that I won't see the issue.
worker->Finalize();
Assert::IsTrue(j.executed == j.chunks); // Now we've finished.
What am I missing / doing wrong? Why does the Process()ing of the job have to be guarded by the suspend mutex?
EDIT: Resume() should not have been holding on to the mutex at the time of notification; that's fixed -- the issue persists.
Of course the Process()ing of the job does not have to be guarded by the suspend mutex.
The access of j.executed - for the asserts as well as for the incrementing - however does need to be synchronized (either by making it an std::atomic<int> or by guarding it with a mutex etc.).
It's still not clear why the issue manifested the way it did (since I'm not writing to the variable on the main thread) -- might be a case of undefined behaviour propagating backwards in time.

How to search through next available thread to do computation

I am doing multithreading in C++. This may be something very standard but I can't seem to find it anywhere or know any key terms to search for it online.
I want to do some sort of computation many times but with multiple threads. For each iteration of computation, I want to find the next available thread that has finished its previous computation to do the next iteration. I don't want to cycle through the threads in order since the next thread to be called may not have finished its work yet.
E.g.
Suppose I have a vector of int and I want to sum up the total with 5 threads. I have the to-be-updated total sum stored somewhere and the count for which element I am currently up to. Each thread looks at the count to see the next position and then takes that vector value and adds it to the total sum so far. Then it goes back to look for the count to do the next iteration. So for each iteration, the count increments then looks for the next available thread (maybe one already waiting for count; or maybe they are all busy still working) to do the next iteration. We do not increase the number of threads but I want to be able to somehow search through all the 5 threads for the first one that finish to do the next computation.
How would I go about coding this. Every way I know of involves doing a loop through the threads such that I can't check for the next available one which may be out of order.
Use semafor (or mutex, always mix up those two) on a global variable telling you what is next. The semafor will lock the other threads out as long as you access the variable making that threads access clear.
So, assuming you have an Array of X elements. And a global called nextfree witch is initalized to 0, then a psudo code would look like this:
while (1)
{
<lock semafor INT>
if (nextfree>=X)
{
<release semnafor INT>
<exit and terminate thread>
}
<Get the data based on "nextfree">
nextfree++;
<release semafor INT>
<do your stuff withe the chunk you got>
}
The point here is that each thread will be alone and have exlusive access to the data struct within the semafor lock and therefore can access the next available regardless of what the others doing. (The other threads will have to wait in line if they are done while another thread working on getting next data chunk. When you release only ONE that stands in queue will get access. The rest will have to wait.)
There are some things to be ware of. Semafor's might lock your system if you manage to exit in the wrong position (Withour releasing it) or create a deadlock.
This is a thread pool:
template<class T>
struct threaded_queue {
using lock = std::unique_lock<std::mutex>;
void push_back( T t ) {
{
lock l(m);
data.push_back(std::move(t));
}
cv.notify_one();
}
boost::optional<T> pop_front() {
lock l(m);
cv.wait(l, [this]{ return abort || !data.empty(); } );
if (abort) return {};
auto r = std::move(data.back());
data.pop_back();
return std::move(r);
}
void terminate() {
{
lock l(m);
abort = true;
data.clear();
}
cv.notify_all();
}
~threaded_queue()
{
terminate();
}
private:
std::mutex m;
std::deque<T> data;
std::condition_variable cv;
bool abort = false;
};
struct thread_pool {
thread_pool( std::size_t n = 1 ) { start_thread(n); }
thread_pool( thread_pool&& ) = delete;
thread_pool& operator=( thread_pool&& ) = delete;
~thread_pool() = default; // or `{ terminate(); }` if you want to abandon some tasks
template<class F, class R=std::result_of_t<F&()>>
std::future<R> queue_task( F task ) {
std::packaged_task<R()> p(std::move(task));
auto r = p.get_future();
tasks.push_back( std::move(p) );
return r;
}
template<class F, class R=std::result_of_t<F&()>>
std::future<R> run_task( F task ) {
if (threads_active() >= total_threads()) {
start_thread();
}
return queue_task( std::move(task) );
}
void terminate() {
tasks.terminate();
}
std::size_t threads_active() const {
return active;
}
std::size_t total_threads() const {
return threads.size();
}
void clear_threads() {
terminate();
threads.clear();
}
void start_thread( std::size_t n = 1 ) {
while(n-->0) {
threads.push_back(
std::async( std::launch::async,
[this]{
while(auto task = tasks.pop_front()) {
++active;
try{
(*task)();
} catch(...) {
--active;
throw;
}
--active;
}
}
)
);
}
}
private:
std::vector<std::future<void>> threads;
threaded_queue<std::packaged_task<void()>> tasks;
std::atomic<std::size_t> active;
};
You give it how many threads either at construction or via start_thread.
You then queue_task. This returns a std::future that tells you when the task is completed.
As threads finish a task, they go to the threaded_queue and look for more.
When a threaded_queue is destroyed, it aborts all data in it.
When a thread_pool is destroyed, it aborts all future tasks, then waits for all of the outstanding tasks to finish.
Live example.

boost::thread execution

I have a class ChunkManager that has a few (supposed to be) asynchronous methods. These methods handle tasks in my game engine such as loading the map blocks (similar to Minecraft) on a different thread so as not to completely halt the main thread (they are lengthy operations)
Here is one of those methods:
void ChunkManager::asyncRenderChunks(){
boost::thread loadingThread(&ChunkManager::renderChunks,this);
}
Where renderChunks looks like:
void ChunkManager::renderChunks(){
activeChunksMutex->lock();
for(int z=0; z < CHUNK_MAX; z=z+1)
{
for(int y=0; y < CHUNK_MAX; y=y+1)
{
for(int x=0; x < CHUNK_MAX; x=x+1)
{
activeChunks[x][y][z]->Render(scnMgr);
}
}
}
activeChunksMutex->unlock();
}
This should work, right? However it crashes when this runs. I have a feeling it has to do with what I do with the thread after it's created, because if I put
loadingThread.join();
in the aforementioned method, it works fine, but the main thread is halted because obviously its just waiting for the new thread to finish, effectively bringing me back to square one.
Any advice?
Sorry if this is a retarded question, I am new to the concept of threads.
Thanks.
Update (4/9/2013):
I found this gem: http://threadpool.sourceforge.net/
..and solved my problem!
If you can join the thread, it must be joinable.
As it says in the documentation:
When the boost::thread object that represents a thread of execution is destroyed the program terminates if the thread is joinable.
You created a local thread object and immediately let it go out of scope: it is destroyed when ChunkManager::asyncRenderChunks returns.
Either:
make it a detached (non-joinable) thread
void ChunkManager::asyncRenderChunks() {
boost::thread loadingThread(&ChunkManager::renderChunks,this);
loadingThread.detach();
}
or create the thread object elsewhere and keep it alive
class ChunkManager {
boost::thread renderingThread;
bool renderChunkWork; // work to do flag
Chunk activeChunks[CHUNK_MAX][CHUNK_MAX][CHUNK_MAX];
boost::mutex activeChunksMutex;
boost::condition_variable activeChunksCV;
bool shutdown; // shutdown flag
void renderChunks() {
for(int z=0; z < CHUNK_MAX; ++z)
for(int y=0; y < CHUNK_MAX; ++y)
for(int x=0; x < CHUNK_MAX; ++x)
activeChunks[x][y][z]->Render(scnMgr);
}
void renderChunkThread() {
boost::unique_lock<boost::mutex> guard(activeChunksMutex);
while (true) {
while (!(renderChunkWork || shutdown))
activeChunksCV.wait(guard);
if (shutdown)
break;
renderChunks();
doRenderChunks = false;
}
}
public:
ChunkManager()
: loadingThread(&ChunkManager::renderChunkThread, this),
renderChunkWork(false), shutdown(false)
{}
~ChunkManager() {
{ // tell the rendering thread to quit
boost::unique_lock<boost::mutex> guard(activeChunksMutex);
renderChunkShutdown = true;
activeChunksCV.notify_one();
}
renderingThread.join()
}
void asyncRenderChunks() {
boost::unique_lock<boost::mutex> guard(activeChunksMutex);
if (!renderChunkWork) {
renderChunkWork = true;
activeChunksCV.notify_one();
}
}
};
NB. In general, creating threads on-the-fly is less good than creating your threads up-front, and just waking them when there's something to do. It avoids figuring out how to handle a second call to asyncRenderChunks before the last one is complete (start a second thread? block?), and moves the latency associated with thread creation.
Note on object lifetime
It's important to realise that in this code:
void ChunkManager::asyncRenderChunks() {
SomeType myObject;
}
the instance myObject will be created and then immediately destroyed.
It crashes, because in the current version of Boost.Thread, you have to either join() a thread or detach() it - otherwise ~thread would terminate the program. (In earlier versions ~thread used to call detach() automatically.)
So if you don't want to join the thread - just detach it:
boost::thread loadingThread(&ChunkManager::renderChunks,this);
loadingThread.detach();

Invoke Windows Form Thread and Sleeping

I have a managed c++ application that I start a new thread to do some stuff and update some text boxes, it loops and sleeps at the end of every loop. Because of it sleeping I needed to have it in a new thread so the UI doesn't crash. Then I realized I need to invoke the thread that created the UI to access the textboxes, but now I'm back in the main thread so the sleeping crashes it. How should I approach this.
private: System::Void buttonStartCamera_Click(System::Object^ sender, System::EventArgs^ e)
{
ThreadStart^ threadStart = gcnew ThreadStart(this, &UserInterface::SetText);
Thread^ newThread = gcnew Thread(threadStart);
newThread->Start();
}
void SetText()
{
if (this->textBoxCameraOneX->InvokeRequired)
{
MyDel^ del = gcnew MyDel(this, &UserInterface::SetText);
this->Invoke(del);
}
else
{
int count = 0;
srand (time(NULL));
for (count = 0; count < 20; ++count)
{
for each (Camera^ camera in cameraList)
{
textBoxCameraOneX->Text = count.ToString();
}
Sleep(300);
}
}
}
The best option is likely to refactor this so your Sleep doesn't occur within the SetText method. Your background thread could use a separate method that performs the sleep, and then invokes the proper method to set the text (for one text box at a time) in a loop.
In general, you should keep the methods you use with Control::Invoke as short as possible - they should only include the logic required for your UI work, and not the other functionality.
That being said, in this case, it seems like a System::Windows::Forms::Timer would be more appropriate. You could set the interval to 300, and update a text box one at a time in the timer's Tick event.

Boost::thread, glut and data sharing

I think I have a problem in my program.
I must create an object that continuosly communicate with an external tracking system and get coordinates of point from it.
I wrapped this class inside a boost::thread and before the first calls to my Glut Application I create the thread object and I detach it
The code for the salient methods of the class is the following
boost::mutex resourceMutex;
void Tracker::init()
{
boost::mutex::scoped_lock lock(resourceMutex);
try
{
// some initializations
}
catch (std::bad_alloc const&)
{
cerr << "Memory allocation fail during init!" << endl;
}
try
{
p3dData = (Position3d*)calloc( NUM_MARKERS , sizeof( Position3d ) );
if ( p3dData==NULL )
throw std::bad_alloc();
}
catch ( std::bad_alloc const&)
{
cerr << "Memory allocation fail during memory allocation!" << endl;
}
}
void Tracker::update()
{
boost::mutex::scoped_lock lock(optotrakResourceMutex);
//... operations on vector< Eigen::Vector3d > points
}
vector<Eigen::Vector3d> &Tracker::getAllPoints()
{
return points;
}
My glutTimerFunc makes a call to an update function that every frame picks the points with the method getAllPoints, while the tracker thread continuosly update them (in fact the frequencies of access to data are different, the thread calls to is faster than the glut update functions calls.
Now when the program exit, I first delete the Tracker object allocated with new then interrupt the thread containing it, but sometimes I get strange behaviours I think they are memory leak
Is the way of getting data with different frequencies of access and the use of scoped_lock correct or should I put some guard in the getAllPoints method?
I understand your dedicated tracker thread continuously calls Tracker::update() to acquire the localization data from your device (NDI Optotrak?)
Then, your OpenGL application accesses the latest points at regular interval from the main thread using Tracker::getAllPoints().
In this case, the vector of 3D points Tracker::points is a shared resource between these two threads.
To prevent concurrent access, both the writing operation in update() and the reading with getAllPoints() must be protected by the mutex, not only the writing as in your current code. The reading code in the main thread must also lock the mutex:
// In your main application:
void timerFunc()
{
Tracker* tracker = ...; // Obtain a pointer to the tracker object
tracker->LockResourceMutex(); // Enter critical section
vector< Eigen::Vector3d >& pointsRef = tracker->getAllPoints();
//... operations on points, protected by the mutex
tracker->UnlockResourceMutex(); // Leave critical section
}
// In class Tracker:
void Tracker::LockResourceMutex() { optotrakResourceMutex.lock(); }
void Tracker::UnlockResourceMutex() { optotrakResourceMutex.unlock(); }
Caveat: If your operations on points in the timerFunc() are slow, then the mutex will remain locked for a long time and your tracker thread will block on it when calling Tracker::update().
A better design would be to change Tracker::getAllPoints() to return a copy of the 3D points vector instead of a reference:
// In class Tracker:
vector<Eigen::Vector3d> Tracker::getAllPoints()
{
boost::mutex::scoped_lock lock(optotrakResourceMutex);
return points; // Will call the std::vector() copy constructor
}
// In your main application:
void timerFunc()
{
Tracker* tracker = ...; // Obtain a pointer to the tracker object
vector< Eigen::Vector3d > myPoints = tracker->getAllPoints();
//... operations on your own copy if points
}
Note how the mutex is encapsulated in the Tracker class and how the timerFunc() does not need to worry about it.
Also note how the mutex is locked only during the copy. The copy of a list of 3D vectors is certainly going to be faster than mathematical operations on them.

Resources