Reputation: 9292
I wrote a simple test program which accumulates random samples to a buffer using multiple threads. Each thread uses a stack for reducing the mutex waits. This is for investigating problems in a much larger program.
The code currently crashes on mingw-w64 4.9.2
Any idea why?
Debugging halts on "signal-received" in a non-usable place (ntdll!DbgBreakPoint)
#include <iostream>
#include <vector>
#include <random>
#include <thread>
#include <mutex>
#include <cstdint>
//The function which will be run concurrently in several threads
void work(float * buf, uint64_t * ns, std::mutex * mtx)
{
std::mt19937 generator;
std::uniform_real_distribution<double> distrib(0., 1.);
std::vector<float> stack;
unsigned int stackPos = 0;
for(unsigned int i=0;i<1000000;i++)
{
//Generate a random sample uniformly between 0 and 1
double sample = distrib(generator);
//Append the sample to the stack
if(stackPos>=stack.size())
{
stack.resize(stackPos+1);
}
stack[stackPos] = sample;
++stackPos;
//Try to acquire the accumulation buffer
bool locked = mtx->try_lock();
//Force aquire if the stack is too large and if try_lock failed
if(!locked && stackPos>2000)
{
mtx->lock();
locked = true;
}
//If the buffer lock is aquired, flush the stack
if(locked)
{
for(unsigned int i=0;i<stackPos;i++)
{
*buf += stack[i];
*ns = *ns + 1;
}
stackPos = 0;
//And unlock
mtx->unlock();
}
}
}
int main()
{
float buffer = 0;
uint64_t numSamples = 0;
std::mutex mtx;
//Start a couple of parallel threads
std::vector<std::thread> workers;
for(unsigned int i=0;i<16;i++)
{
workers.emplace_back(std::thread(work, &buffer, &numSamples, &mtx));
}
//This will join the threads
workers.clear();
std::cout << "Average : " << buffer/numSamples << std::endl;
return 0;
}
Upvotes: 0
Views: 881
Reputation: 180660
workers.clear();
is not going to join all of the threads. Calling clear()
will call the threads' deconstructors. std::thread::~thread
will call std::terminate()
if the thread is joinable()
. Since you are calling clear()
on the vector right after you create the vector the threads are still processing and are joinable.
You have to join all threads manually before deleting them:
int main()
{
// […]
//This will join the threads
for (std::thread& thread : workers)
{
thread.join();
}
workers.clear();
return 0;
}
Upvotes: 4