1 /* Threads.c -- multithreading library
2 2008-08-05
3 Igor Pavlov
4 Public domain */
5 
6 #include "Threads.h"
7 #include <process.h>
8 
GetError()9 static WRes GetError()
10 {
11   DWORD res = GetLastError();
12   return (res) ? (WRes)(res) : 1;
13 }
14 
HandleToWRes(HANDLE h)15 WRes HandleToWRes(HANDLE h) { return (h != 0) ? 0 : GetError(); }
BOOLToWRes(BOOL v)16 WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); }
17 
MyCloseHandle(HANDLE * h)18 static WRes MyCloseHandle(HANDLE *h)
19 {
20   if (*h != NULL)
21     if (!CloseHandle(*h))
22       return GetError();
23   *h = NULL;
24   return 0;
25 }
26 
Thread_Create(CThread * thread,THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * startAddress)(void *),LPVOID parameter)27 WRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter)
28 {
29   unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */
30   thread->handle =
31     /* CreateThread(0, 0, startAddress, parameter, 0, &threadId); */
32     (HANDLE)_beginthreadex(NULL, 0, startAddress, parameter, 0, &threadId);
33     /* maybe we must use errno here, but probably GetLastError() is also OK. */
34   return HandleToWRes(thread->handle);
35 }
36 
WaitObject(HANDLE h)37 WRes WaitObject(HANDLE h)
38 {
39   return (WRes)WaitForSingleObject(h, INFINITE);
40 }
41 
Thread_Wait(CThread * thread)42 WRes Thread_Wait(CThread *thread)
43 {
44   if (thread->handle == NULL)
45     return 1;
46   return WaitObject(thread->handle);
47 }
48 
Thread_Close(CThread * thread)49 WRes Thread_Close(CThread *thread)
50 {
51   return MyCloseHandle(&thread->handle);
52 }
53 
Event_Create(CEvent * p,BOOL manualReset,int initialSignaled)54 WRes Event_Create(CEvent *p, BOOL manualReset, int initialSignaled)
55 {
56   p->handle = CreateEvent(NULL, manualReset, (initialSignaled ? TRUE : FALSE), NULL);
57   return HandleToWRes(p->handle);
58 }
59 
ManualResetEvent_Create(CManualResetEvent * p,int initialSignaled)60 WRes ManualResetEvent_Create(CManualResetEvent *p, int initialSignaled)
61   { return Event_Create(p, TRUE, initialSignaled); }
ManualResetEvent_CreateNotSignaled(CManualResetEvent * p)62 WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p)
63   { return ManualResetEvent_Create(p, 0); }
64 
AutoResetEvent_Create(CAutoResetEvent * p,int initialSignaled)65 WRes AutoResetEvent_Create(CAutoResetEvent *p, int initialSignaled)
66   { return Event_Create(p, FALSE, initialSignaled); }
AutoResetEvent_CreateNotSignaled(CAutoResetEvent * p)67 WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p)
68   { return AutoResetEvent_Create(p, 0); }
69 
Event_Set(CEvent * p)70 WRes Event_Set(CEvent *p) { return BOOLToWRes(SetEvent(p->handle)); }
Event_Reset(CEvent * p)71 WRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(p->handle)); }
Event_Wait(CEvent * p)72 WRes Event_Wait(CEvent *p) { return WaitObject(p->handle); }
Event_Close(CEvent * p)73 WRes Event_Close(CEvent *p) { return MyCloseHandle(&p->handle); }
74 
75 
Semaphore_Create(CSemaphore * p,UInt32 initiallyCount,UInt32 maxCount)76 WRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount)
77 {
78   p->handle = CreateSemaphore(NULL, (LONG)initiallyCount, (LONG)maxCount, NULL);
79   return HandleToWRes(p->handle);
80 }
81 
Semaphore_Release(CSemaphore * p,LONG releaseCount,LONG * previousCount)82 WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount)
83 {
84   return BOOLToWRes(ReleaseSemaphore(p->handle, releaseCount, previousCount));
85 }
Semaphore_ReleaseN(CSemaphore * p,UInt32 releaseCount)86 WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount)
87 {
88   return Semaphore_Release(p, (LONG)releaseCount, NULL);
89 }
Semaphore_Release1(CSemaphore * p)90 WRes Semaphore_Release1(CSemaphore *p)
91 {
92   return Semaphore_ReleaseN(p, 1);
93 }
94 
Semaphore_Wait(CSemaphore * p)95 WRes Semaphore_Wait(CSemaphore *p) { return WaitObject(p->handle); }
Semaphore_Close(CSemaphore * p)96 WRes Semaphore_Close(CSemaphore *p) { return MyCloseHandle(&p->handle); }
97 
CriticalSection_Init(CCriticalSection * p)98 WRes CriticalSection_Init(CCriticalSection *p)
99 {
100   /* InitializeCriticalSection can raise only STATUS_NO_MEMORY exception */
101   __try
102   {
103     InitializeCriticalSection(p);
104     /* InitializeCriticalSectionAndSpinCount(p, 0); */
105   }
106   __except (EXCEPTION_EXECUTE_HANDLER) { return 1; }
107   return 0;
108 }
109 
110