1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
#include "MultiThreading.h"
THREAD_HANDLE CreateThreadPortable (void *(*start_routine) (void *), void *arg)
{
#if defined _WIN32 || defined _WIN64
return CreateThread (0, 0, (LPTHREAD_START_ROUTINE)start_routine, (LPVOID)arg, 0, 0);
#else
THREAD_HANDLE th = (THREAD_HANDLE)malloc(sizeof(pthread_t));
if (!th)
{
std::cerr << "Error allocating thread." << std::endl;
return NULL;
}
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if(int err = pthread_create(th, &attr, start_routine, arg))
{
std::cerr << strerror(err) << std::endl;
return NULL;
}
return th;
#endif
}
void DestroyThreadPortable (THREAD_HANDLE th)
{
#if !defined _WIN32 && !defined _WIN64
if(th)
free(th);
#endif
}
/****************************************************************************
* Condition variables for Windows XP and older windows sytems
*****************************************************************************/
#if defined WINXPOROLDER
void InitCondition (condition_variable_t *cv)
{
InitializeCriticalSection(&cv->waitersCountLock);
cv->waitersCount = 0;
cv->waitGenerationCount = 0;
cv->releaseCount = 0;
cv->waitingEvent = CreateEvent (NULL, // no security
TRUE, // manual-reset
FALSE, // non-signaled initially
NULL); // unnamed
}
void WaitCondition (condition_variable_t *cv, CRITICAL_SECTION *externalMutex)
{
EnterCriticalSection(&cv->waitersCountLock);
cv->waitersCount++;
int currentGenerationCount = cv->waitGenerationCount;
LeaveCriticalSection(&cv->waitersCountLock);
LeaveCriticalSection(externalMutex);
bool isWaitDone = false;
while(!isWaitDone)
{
WaitForSingleObject (cv->waitingEvent, INFINITE);
EnterCriticalSection (&cv->waitersCountLock);
isWaitDone = (cv->releaseCount > 0 && cv->waitGenerationCount != currentGenerationCount);
LeaveCriticalSection (&cv->waitersCountLock);
}
EnterCriticalSection(externalMutex);
EnterCriticalSection(&cv->waitersCountLock);
cv->waitersCount--;
cv->releaseCount--;
bool isLastWaiter = (cv->releaseCount == 0);
LeaveCriticalSection(&cv->waitersCountLock);
if(isLastWaiter)
ResetEvent(cv->waitingEvent);
}
void SignalCondition (condition_variable_t *cv)
{
EnterCriticalSection(&cv->waitersCountLock);
if(cv->waitersCount > cv->releaseCount)
{
SetEvent(cv->waitingEvent);
cv->releaseCount++;
cv->waitGenerationCount++;
}
LeaveCriticalSection(&cv->waitersCountLock);
}
void BroadcastCondition (condition_variable_t *cv)
{
EnterCriticalSection(&cv->waitersCountLock);
if(cv->waitersCount > 0)
{
SetEvent(cv->waitingEvent);
cv->releaseCount = cv->waitersCount;
cv->waitGenerationCount++;
}
LeaveCriticalSection(&cv->waitersCountLock);
}
#endif
|