|
-
April 3rd, 2016, 02:09 PM
#1
Using threads and sigaling in plain C++ or Unix
I have written a Windows console app that uses some windows APIs.
Specifically it uses threads (CreateThread, ResumeThread) and signaling(WaitForMulipleObjects, WaitForSingleObject).
The program run fine on Windows. However I want to run this on my Mac. Does anybody know the c++ equivalent for these calls?
Code:
#include <SDKDDKVer.h>
#include <windows.h>
#include <cmath>
#include <iostream>
#include <fstream>
#include <tchar.h>
#include <limits>
#include <mutex>
using namespace std;
#define MAX_INT64 (0X7FFFFFFFFFFFFFFFLL)
#define MOD(a,b) (a%b)
#define SQRT(x) (sqrt(x))
#define TRUNC(x) ((MYTYPE)(x))
#define MAX_WAIT (INFINITE)
#define NUM_BLOCKS (1000)
#define WORKER_THREADS (8)
typedef long long MYTYPE;
typedef long double MYFLOATTYPE;
typedef struct Triple
{
MYTYPE a;
MYTYPE b;
MYTYPE c;
} Triple;
typedef struct TripleBlock
{
Triple* Triples;
long NumTriples;
long NumTriplesAllocated;
TripleBlock* Next;
} TripleBlock;
typedef struct ThreadStartData
{
MYTYPE min;
MYTYPE startmax;
MYTYPE max;
MYTYPE numdone;
MYTYPE numthreads;
MYTYPE complete;
TripleBlock* block;
} ThreadStartData;
void PrintTriples(TripleBlock* block);
TripleBlock* AllocateTripleBlock(long numtriples);
void AddTriple(MYTYPE a, MYTYPE b, MYTYPE c, TripleBlock* block);
DWORD WINAPI CalculateTriples(LPVOID lpParam);
DWORD WINAPI ProgressTriples(LPVOID lpParam);
std::mutex m;
ofstream myfile;
int _tmain(int argc, _TCHAR* argv[])
{
MYTYPE min = 2;
MYTYPE max = 0;
if (argc == 1)
{
max = MAX_INT64;
}
else if (argc == 2)
{
max = _ttol(argv[1]);
}
else
{
cout << argv[0] << " max" << endl;
return 0;
}
int numThreads = WORKER_THREADS;
if (max < WORKER_THREADS * 5)
numThreads = 1;
cout << "Using " << numThreads << " worker threads." << endl;
DWORD* dwThreadIdArray = (DWORD*) malloc(numThreads * sizeof(DWORD));
HANDLE* hThreadArray = (HANDLE*) malloc(numThreads * sizeof(HRESULT));
ThreadStartData* data = (ThreadStartData*) malloc(numThreads * sizeof(ThreadStartData));
memset(dwThreadIdArray, 0, numThreads * sizeof(DWORD));
memset(hThreadArray, 0, numThreads * sizeof(HRESULT));
memset(data, 0, numThreads * sizeof(sizeof(ThreadStartData)));
MYTYPE inc = max / numThreads;
m.lock();
for (int i = 0; i < numThreads; i++)
{
data[i].min = min;
data[i].max = max;
data[i].numdone = 0;
data[i].numthreads = numThreads;
data[i].complete = 0;
data[i].block = AllocateTripleBlock(NUM_BLOCKS);
MYTYPE startmax = min + inc;
if (startmax > max)
startmax = max;
data[i].startmax = startmax;
if (data[i].startmax > max)
data[i].startmax = max;
min += (inc + 1);
hThreadArray[i] = CreateThread(
NULL, // default security attributes
0, // use default stack size
CalculateTriples, // thread function name
&data[i], // argument to thread function
CREATE_SUSPENDED, // creation flags
&dwThreadIdArray[i]); // returns the thread identifier
}
DWORD dwProgressThreadID;
HANDLE hProgressthread = CreateThread(
NULL, // default security attributes
0, // use default stack size
ProgressTriples, // thread function name
data, // argument to thread function
CREATE_SUSPENDED, // creation flags
&dwProgressThreadID); // returns the thread identifier
m.unlock();
for(int i=0; i < numThreads; i++)
{
SetThreadPriority(hThreadArray[i], THREAD_PRIORITY_ABOVE_NORMAL);
ResumeThread(hThreadArray[i]);
}
ResumeThread(hProgressthread);
// wait for all the threads to complete
DWORD result = 0;
MYTYPE lastPercent = -1;
WaitForMultipleObjects(numThreads, hThreadArray, TRUE, MAX_WAIT);
WaitForSingleObject(hProgressthread, MAX_WAIT);
// print the results
myfile.open("triples.txt");
for (int i = 0; i < numThreads; i++)
{
PrintTriples(data[i].block);
}
myfile.close();
cout << endl << endl;
// cleanup
for (int i = 0; i < numThreads; i++)
{
TripleBlock* block = data[i].block;
while (block)
{
TripleBlock* next = block->Next;
if (block->NumTriplesAllocated > 0)
free(block->Triples);
free(block);
block = next;
}
CloseHandle(hThreadArray[i]);
}
free(dwThreadIdArray);
free(data);
return 0;
}
/// <summary>
/// show progress thread.
/// </summary>
/// <param name="lpParam">The lp parameter.</param>
/// <returns>DWORD.</returns>
DWORD WINAPI ProgressTriples(LPVOID lpParam)
{
ThreadStartData* data = (ThreadStartData*)lpParam;
MYTYPE numThreads = data->numthreads;
MYTYPE max = data->max;
MYTYPE lastPercent = -1;
bool done = true;
do
{
MYTYPE total = 0;
done = true;
for (int i = 0; i < numThreads; i++)
{
total += data[i].numdone;
if (data[i].complete == 0)
done = false;
}
if (done)
{
cout << "done." << endl;
break;
}
MYFLOATTYPE percentdone = ((MYFLOATTYPE)total / (MYFLOATTYPE)max) * 100;
if (lastPercent != TRUNC(percentdone))
{
lastPercent = TRUNC(percentdone);
cout << lastPercent << "% done. (" << total << " of " << max << ")" << endl;
Sleep(1 * 1000);
}
}
while (!done);
return 0;
}
/// <summary>
/// Calculates the triples.
/// </summary>
/// <param name="lpParam">The lp parameter.</param>
/// <returns>DWORD.</returns>
DWORD WINAPI CalculateTriples(LPVOID lpParam)
{
ThreadStartData* data = (ThreadStartData*)lpParam;
MYTYPE min = data->min;
MYTYPE max = data->max;
MYTYPE startmax = data->startmax;
TripleBlock* block = data->block;
for (MYTYPE a = min; a >= min && a < startmax; a++)
{
data->numdone++;
MYFLOATTYPE asquared = (MYFLOATTYPE)a * (MYFLOATTYPE)a;
for (MYTYPE b = a + 1; b > a; b += 2)
{
MYFLOATTYPE bsquared = (MYFLOATTYPE)b * (MYFLOATTYPE)b;
MYFLOATTYPE csquared = asquared + bsquared;
MYFLOATTYPE csqroot = SQRT(csquared);
MYTYPE c = TRUNC(csqroot);
// check for max
if (c > max || c < b)
break;
// check for a true square
if (csqroot != TRUNC(csqroot))
continue;
// check gcd
MYTYPE i = 0;
for (i = a; i >= 1; i--)
{
if (MOD(c, i) != 0)
continue;
if (MOD(b, i) != 0)
continue;
if (MOD(a, i) != 0)
continue;
break;
}
// if gcd != 1 then no triplet
if (i != 1)
{
continue;
}
AddTriple(a, b, c, block);
break;
}
}
data->complete = -1;
return 0;
}
/// <summary>
/// Adds the triple.
/// </summary>
/// <param name="a">a.</param>
/// <param name="b">b.</param>
/// <param name="c">c.</param>
/// <param name="block">block.</param>
void AddTriple(MYTYPE a, MYTYPE b, MYTYPE c, TripleBlock* block)
{
while (block->NumTriples >= block->NumTriplesAllocated)
{
if (block->Next == NULL)
{
block->Next = AllocateTripleBlock(NUM_BLOCKS);
}
block = block->Next;
}
Triple* triple = &(block->Triples[block->NumTriples]);
triple->a = a;
triple->b = b;
triple->c = c;
block->NumTriples++;
}
/// <summary>
/// Allocates the triple block.
/// </summary>
/// <param name="numtriples">The numtriples.</param>
/// <returns>TripleBlock *</returns>
TripleBlock* AllocateTripleBlock(long numtriples)
{
TripleBlock* block = (TripleBlock*) malloc(sizeof(TripleBlock));
if (block == NULL)
return NULL;
memset(block, 0, sizeof(TripleBlock));
block->NumTriplesAllocated = numtriples;
block->Triples = (Triple*) malloc(numtriples * sizeof(Triple));
if (block->Triples == NULL)
return NULL;
memset(block->Triples, 0, numtriples * sizeof(Triple));
return block;
}
/// <summary>
/// Prints the triples.
/// </summary>
/// <param name="block">The block.</param>
void PrintTriples(TripleBlock* block)
{
while (block)
{
Triple* triple = block->Triples;
for (MYTYPE i = 0; i < block->NumTriples; i++, triple++)
{
myfile << " " << triple->a << ", " << triple->b << ", " << triple->c << endl;
}
block = block->Next;
}
}
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|