following some former advice
Multithreaded application, am I doing it right?
I think I have a threadsafe number generator using boost, but my program crashes when I input 1000 iterations. The output .csv file when graphed looks right, but I'm not sure why it's crashing.
It's using _beginthread, and everyone is telling me I should use the more (convoluted) _beingthreadex, which I'm not familiar with. If someone could recommend an example, I would greatly appreciate it.
Also... someone pointed out I should be applying a second parameter to my _beginthread for the array counting start positions, but I have no idea how to pass more than one parameter, other than attempting to use a structure, and I've read structure's and _beginthread don't get along (although, I could just use the boost threads...)
#include <process.h>
#include <windows.h>
#include <iostream>
#include <fstream>
#include <time.h>
#include <random>
#include <boost/random.hpp>
//for srand48_r(time(NULL), &randBuffer); which doesn't work
#include <stdio.h>
#include <stdlib.h>
//#include <thread>
using namespace std;
using namespace boost;
using namespace boost::random;
void myThread0 (void *dummy );
void myThread1 (void *dummy );
void myThread2 (void *dummy );
void myThread3 (void *dummy );
//for random seeds
void initialize();
//from http://stackoverflow.com/questions/7114043/random-number-generation-in-c11-how-to-generate-how-do-they-work
uniform_int_distribution<> two(1,2);
typedef std::mt19937 MyRNG; // the Mersenne Twister with a popular choice of parameters
uint32_t seed_val; // populate somehow
MyRNG rng1; // e.g. keep one global instance (per thread)
MyRNG rng2; // e.g. keep one global instance (per thread)
MyRNG rng3; // e.g. keep one global instance (per thread)
MyRNG rng4; // e.g. keep one global instance (per thread)
//only needed for shared variables
//CRITICAL_SECTION cs1,cs2,cs3,cs4; // global
int main()
{
ofstream myfile;
myfile.open ("coinToss.csv");
int rNum;
long numRuns;
long count = 0;
int divisor = 1;
float fHolder = 0;
long counter = 0;
float percent = 0.0;
//?
//unsigned threadID;
//HANDLE hThread;
initialize();
HANDLE hThread[4];
const int size = 100000;
int array[size];
printf ("Runs (uses multiple of 100,000) ");
cin >> numRuns;
for (int a = 0; a < numRuns; a++)
{
hThread[0] = (HANDLE)_beginthread( myThread0, 0, (void*)(array) );
hThread[1] = (HANDLE)_beginthread( myThread1, 0, (void*)(array) );
hThread[2] = (HANDLE)_beginthread( myThread2, 0, (void*)(array) );
hThread[3] = (HANDLE)_beginthread( myThread3, 0, (void*)(array) );
//waits for threads to finish before continuing
WaitForMultipleObjects(4, hThread, TRUE, INFINITE);
//closes handles I guess?
CloseHandle( hThread[0] );
CloseHandle( hThread[1] );
CloseHandle( hThread[2] );
CloseHandle( hThread[3] );
//dump array into calculations
//average array into fHolder
//this could be split into threads as well
for (int p = 0; p < size; p++)
{
counter += array[p] == 2 ? 1 : -1;
//cout << array[p] << endl;
//cout << counter << endl;
}
//this fHolder calculation didn't work
//fHolder = counter / size;
//so I had to use this
cout << counter << endl;
fHolder = counter;
fHolder = fHolder / size;
myfile << fHolder << endl;
}
}
void initialize()
{
//seed value needs to be supplied
//rng1.seed(seed_val*1);
rng1.seed((unsigned int)time(NULL));
rng2.seed(((unsigned int)time(NULL))*2);
rng3.seed(((unsigned int)time(NULL))*3);
rng4.seed(((unsigned int)time(NULL))*4);
};
void myThread0 (void *param)
{
//EnterCriticalSection(&cs1); //aquire the critical section object
int *i = (int *)param;
for (int x = 0; x < 25000; x++)
{
//doesn't work, part of merssene twister
//i[x] = next();
i[x] = two(rng1);
//original srand
//i[x] = rand() % 2 + 1;
//doesn't work for some reason.
//uint_dist2(rng);
//i[x] = qrand() % 2 + 1;
//cout << i[x] << endl;
}
//LeaveCriticalSection(&cs1); // release the critical section object
}
void myThread1 (void *param)
{
//EnterCriticalSection(&cs2); //aquire the critical section object
int *i = (int *)param;
for (int x = 25000; x < 50000; x++)
{
//param[x] = rand() % 2 + 1;
i[x] = two(rng2);
//i[x] = rand() % 2 + 1;
//cout << i[x] << endl;
}
//LeaveCriticalSection(&cs2); // release the critical section object
}
void myThread2 (void *param)
{
//EnterCriticalSection(&cs3); //aquire the critical section object
int *i = (int *)param;
for (int x = 50000; x < 75000; x++)
{
i[x] = two(rng3);
//i[x] = rand() % 2 + 1;
//cout << i[x] << endl;
}
//LeaveCriticalSection(&cs3); // release the critical section object
}
void myThread3 (void *param)
{
//EnterCriticalSection(&cs4); //aquire the critical section object
int *i = (int *)param;
for (int x = 75000; x < 100000; x++)
{
i[x] = two(rng4);
//i[x] = rand() % 2 + 1;
//cout << i[x] << endl;
}
//LeaveCriticalSection(&cs4); // release the critical section object
}