-
Notifications
You must be signed in to change notification settings - Fork 71
/
platformSemaphore.c
155 lines (124 loc) · 3.69 KB
/
platformSemaphore.c
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include "pharovm/pharo.h"
#include "pharovm/semaphores/platformSemaphore.h"
/*
* This Functions are private to the implementation
*/
PlatformSemaphore semaphore_new(long initialValue);
int semaphore_wait(PlatformSemaphore sem);
int semaphore_signal(PlatformSemaphore sem);
int semaphore_release(PlatformSemaphore sem);
#if defined(_WIN32)
/*
* Win32 semaphore implementation
* Based on the documentation in
* https://docs.microsoft.com/en-us/windows/win32/sync/using-semaphore-objects
* https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createsemaphorea
*/
PlatformSemaphore
semaphore_new(long initialValue) {
PlatformSemaphore ghSemaphore = CreateSemaphore(
NULL, // default security attributes
initialValue, // initial count
255, // maximum count
NULL); // unnamed semaphore
return ghSemaphore;
}
int
semaphore_wait(PlatformSemaphore sem) {
DWORD returnValue;
returnValue = WaitForSingleObject(
sem, // handle to semaphore
INFINITE) ; // Infinite time-out interval
return (returnValue != WAIT_FAILED) ? 0 : 1; // Should return 0 on Success 1 on failure
}
int
semaphore_signal(PlatformSemaphore sem) {
BOOL returnValue;
returnValue = ReleaseSemaphore(
sem, // handle to semaphore
1, // increase count by one
NULL); // not interested in previous count
return (returnValue != 0) ? 0 : 1; // Should return 0 on Success 1 on failure
}
int
semaphore_release(PlatformSemaphore sem) {
BOOL returnValue;
returnValue = CloseHandle(sem);
return (returnValue != 0) ? 0 : 1; // Should return 0 on Success 1 on failure;
}
#elif !defined(__APPLE__)
PlatformSemaphore
semaphore_new(long initialValue){
PlatformSemaphore wrapper = malloc(sizeof(sem_t));
int returnCode;
returnCode = sem_init(wrapper, 0, initialValue);
if(returnCode != 0){
return NULL;
}
return wrapper;
}
int
semaphore_wait(PlatformSemaphore sem){
int returnCode;
while((returnCode = sem_wait(sem)) == -1 && errno == EINTR);
return returnCode;
}
int
semaphore_signal(PlatformSemaphore sem){
return sem_post(sem);
}
int
semaphore_release(PlatformSemaphore sem){
sem_destroy(sem);
free(sem);
return 0;
}
#else
PlatformSemaphore
semaphore_new(long initialValue){
return dispatch_semaphore_create(initialValue);
}
int
semaphore_wait(PlatformSemaphore sem){
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER );
return 0;
}
int
semaphore_signal(PlatformSemaphore sem){
dispatch_semaphore_signal(sem);
return 0;
}
int
semaphore_release(PlatformSemaphore sem){
/* https://developer.apple.com/documentation/dispatch/1496328-dispatch_release
If your app is built with a deployment target of macOS 10.8 and later or iOS v6.0 and
later, dispatch queues are typically managed by ARC, so you do not need to retain or release
the dispatch queues.
TODO: No idea if this applies (need to check later), but this is crashing the system.
dispatch_release(sem);
*/
return 0;
}
#endif
int
platform_semaphore_wait(Semaphore *semaphore){
return semaphore_wait((PlatformSemaphore)semaphore->handle);
}
int
platform_semaphore_signal(Semaphore *semaphore){
return semaphore_signal((PlatformSemaphore)semaphore->handle);
}
void
platform_semaphore_free(Semaphore *semaphore){
semaphore_release((PlatformSemaphore)semaphore->handle);
free(semaphore);
}
Semaphore*
platform_semaphore_new(int initialValue) {
Semaphore *semaphore = (Semaphore *) malloc(sizeof(Semaphore));
semaphore->handle = (void *) semaphore_new(initialValue);
semaphore->wait = platform_semaphore_wait;
semaphore->signal = platform_semaphore_signal;
semaphore->free = platform_semaphore_free;
return semaphore;
}