1 | Unit Semaphores;
|
---|
2 |
|
---|
3 | Interface
|
---|
4 |
|
---|
5 | Uses
|
---|
6 | {$ifdef os2}
|
---|
7 | BseDos;
|
---|
8 | {$else}
|
---|
9 | Windows;
|
---|
10 | {$endif}
|
---|
11 |
|
---|
12 | Type
|
---|
13 | {$ifdef win32}
|
---|
14 | Hev = THandle;
|
---|
15 | HMtx = THandle;
|
---|
16 | {$endif}
|
---|
17 |
|
---|
18 | TEventSemaphore = class
|
---|
19 | protected
|
---|
20 | _Handle: HEv;
|
---|
21 | _Name: string;
|
---|
22 | _AlreadyExisted: boolean;
|
---|
23 | public
|
---|
24 | Constructor Create;
|
---|
25 | Constructor CreateNamed( const Name: string );
|
---|
26 | Destructor Destroy; override;
|
---|
27 |
|
---|
28 | procedure Post;
|
---|
29 | procedure Reset;
|
---|
30 | function IsPosted: boolean;
|
---|
31 | procedure Wait;
|
---|
32 |
|
---|
33 | property Handle: HEv read _Handle;
|
---|
34 | end;
|
---|
35 |
|
---|
36 | TWaitType = ( wtAny, wtAll );
|
---|
37 |
|
---|
38 | {$ifdef os2}
|
---|
39 | TSemaphoreArray = Array[ 0..0 ] of SEMRECORD;
|
---|
40 | TPSemaphoreArray = ^TSemaphoreArray;
|
---|
41 | {$else}
|
---|
42 | TSemaphoreArray = Array[ 0..0 ] of TEventSemaphore;
|
---|
43 | TPSemaphoreArray = ^TSemaphoreArray;
|
---|
44 | {$endif}
|
---|
45 |
|
---|
46 | TMultiWaitSemaphore = class
|
---|
47 | protected
|
---|
48 | _WaitType: TWaitType;
|
---|
49 | {$ifdef os2}
|
---|
50 | _Handle: HMux;
|
---|
51 | _PSemaphoreArray: TPSemaphoreArray;
|
---|
52 | {$else}
|
---|
53 | _PSemaphoreHandleArray: PWOHandleArray;
|
---|
54 | _PSemaphoreArray: TPSemaphoreArray;
|
---|
55 | {$endif}
|
---|
56 | _SemaphoreCount: longint;
|
---|
57 | public
|
---|
58 | Constructor Create( WaitType: TWaitType;
|
---|
59 | Semaphores: array of TEventSemaphore );
|
---|
60 | Destructor Destroy; Override;
|
---|
61 |
|
---|
62 | // Returns which event semaphore was posted
|
---|
63 | Function Wait: TEventSemaphore;
|
---|
64 | end;
|
---|
65 |
|
---|
66 | TMutex = class
|
---|
67 | protected
|
---|
68 | _Handle: HMtx;
|
---|
69 | public
|
---|
70 | constructor Create;
|
---|
71 | constructor CreateNamed( const Name: string );
|
---|
72 | destructor Destroy; override;
|
---|
73 |
|
---|
74 | procedure Get;
|
---|
75 | procedure Release;
|
---|
76 | end;
|
---|
77 |
|
---|
78 | Implementation
|
---|
79 |
|
---|
80 | // Turn off range checking since we are playing with dynamic arrays
|
---|
81 | {$R-}
|
---|
82 |
|
---|
83 | Constructor TEventSemaphore.Create;
|
---|
84 | begin
|
---|
85 | {$ifdef os2}
|
---|
86 | DosCreateEventSem( nil, // unnamed
|
---|
87 | _Handle,
|
---|
88 | 0, // not shared
|
---|
89 | false );
|
---|
90 | {$else}
|
---|
91 | _Handle:= CreateEvent( nil, // no security
|
---|
92 | true, // manual reset please
|
---|
93 | false, // initially cleared
|
---|
94 | nil ); // no name
|
---|
95 | {$endif}
|
---|
96 | end;
|
---|
97 |
|
---|
98 | Constructor TEventSemaphore.CreateNamed( const Name: string );
|
---|
99 | {$ifdef os2}
|
---|
100 | var
|
---|
101 | CName: Cstring;
|
---|
102 | {$endif}
|
---|
103 | begin
|
---|
104 | _Name := Name;
|
---|
105 | {$ifdef os2}
|
---|
106 | CName := Name;
|
---|
107 | DosCreateEventSem( CName, // unnamed
|
---|
108 | _Handle,
|
---|
109 | DC_SEM_SHARED, // shared
|
---|
110 | false );
|
---|
111 | {$else}
|
---|
112 | _Handle:= CreateEvent( nil, // no security
|
---|
113 | true, // manual reset please
|
---|
114 | false, // initially cleared
|
---|
115 | PChar( name ) ); // no name
|
---|
116 | {$endif}
|
---|
117 | end;
|
---|
118 |
|
---|
119 | Destructor TEventSemaphore.Destroy;
|
---|
120 | begin
|
---|
121 | {$ifdef os2}
|
---|
122 | DosCloseEventSem( _Handle );
|
---|
123 | {$else}
|
---|
124 | CloseHandle( _Handle );
|
---|
125 | {$endif}
|
---|
126 | end;
|
---|
127 |
|
---|
128 | procedure TEventSemaphore.Post;
|
---|
129 | begin
|
---|
130 | {$ifdef os2}
|
---|
131 | DosPostEventSem( _Handle );
|
---|
132 | {$else}
|
---|
133 | SetEvent( _Handle );
|
---|
134 | {$endif}
|
---|
135 | end;
|
---|
136 |
|
---|
137 | procedure TEventSemaphore.Reset;
|
---|
138 | {$ifdef os2}
|
---|
139 | var
|
---|
140 | PostCount: Longword;
|
---|
141 | {$endif}
|
---|
142 | begin
|
---|
143 | {$ifdef os2}
|
---|
144 | DosResetEventSem( _Handle, PostCount );
|
---|
145 | {$else}
|
---|
146 | ResetEvent( _Handle);
|
---|
147 | {$endif}
|
---|
148 | end;
|
---|
149 |
|
---|
150 | function TEventSemaphore.IsPosted: boolean;
|
---|
151 | {$ifdef os2}
|
---|
152 | var
|
---|
153 | PostCount: Longword;
|
---|
154 | {$endif}
|
---|
155 | begin
|
---|
156 | {$ifdef os2}
|
---|
157 | DosQueryEventSem( _Handle, PostCount );
|
---|
158 | Result:= ( PostCount > 0 );
|
---|
159 | {$else}
|
---|
160 | if WaitForSingleObject( _Handle,
|
---|
161 | 0 ) // return immediately...
|
---|
162 | = WAIT_OBJECT_0 then
|
---|
163 | Result:= true
|
---|
164 | else
|
---|
165 | Result:= false;
|
---|
166 | // ? doesn't seem to be possible...
|
---|
167 | {$endif}
|
---|
168 | end;
|
---|
169 |
|
---|
170 | procedure TEventSemaphore.Wait;
|
---|
171 | begin
|
---|
172 | {$ifdef os2}
|
---|
173 | DosWaitEventSem( Handle, SEM_INDEFINITE_WAIT );
|
---|
174 | {$else}
|
---|
175 | WaitForSingleObject( _Handle,
|
---|
176 | INFINITE );
|
---|
177 | {$endif}
|
---|
178 | end;
|
---|
179 |
|
---|
180 | Constructor TMultiWaitSemaphore.Create( WaitType: TWaitType;
|
---|
181 | Semaphores: array of TEventSemaphore );
|
---|
182 | var
|
---|
183 | i: longint;
|
---|
184 | SemIndex: longint;
|
---|
185 |
|
---|
186 | {$ifdef os2}
|
---|
187 | flAttr: Longword;
|
---|
188 | {$endif}
|
---|
189 |
|
---|
190 | begin
|
---|
191 | _WaitType:= WaitType;
|
---|
192 |
|
---|
193 | _SemaphoreCount:= High( Semaphores ) - Low( Semaphores ) + 1;
|
---|
194 | {$ifdef os2}
|
---|
195 | GetMem( _PSemaphoreArray, Sizeof( SEMRECORD ) * _SemaphoreCount );
|
---|
196 | {$else}
|
---|
197 | GetMem( _PSemaphoreHandleArray, Sizeof( THandle ) * _SemaphoreCount );
|
---|
198 | GetMem( _PSemaphoreArray, Sizeof( TEventSemaphore ) * _SemaphoreCount );
|
---|
199 | {$endif}
|
---|
200 |
|
---|
201 | for i:= 0 to _SemaphoreCount - 1 do
|
---|
202 | begin
|
---|
203 | SemIndex:= i + Low( Semaphores );
|
---|
204 | {$ifdef os2}
|
---|
205 | _PSemaphoreArray^[ i ].hSemCur:= Semaphores[ SemIndex ].Handle;
|
---|
206 | _PSemaphoreArray^[ i ].ulUser:= longword( Semaphores[ SemIndex ] );
|
---|
207 | {$else}
|
---|
208 | _PSemaphoreHandleArray^[ i ]:= Semaphores[ SemIndex ].Handle;
|
---|
209 | _PSemaphoreArray^[ i ]:= Semaphores[ SemIndex ];
|
---|
210 | {$endif}
|
---|
211 | end;
|
---|
212 |
|
---|
213 | {$ifdef os2}
|
---|
214 | case _WaitType of
|
---|
215 | wtAll:
|
---|
216 | flAttr:= DCMW_WAIT_ALL;
|
---|
217 | wtAny:
|
---|
218 | flAttr:= DCMW_WAIT_ANY;
|
---|
219 | end;
|
---|
220 |
|
---|
221 | DosCreateMuxWaitSem( nil,
|
---|
222 | _Handle,
|
---|
223 | _SemaphoreCount,
|
---|
224 | _PSemaphoreArray^,
|
---|
225 | flAttr );
|
---|
226 | {$endif}
|
---|
227 | // nothing to do for Win32...
|
---|
228 |
|
---|
229 | end;
|
---|
230 |
|
---|
231 | Destructor TMultiWaitSemaphore.Destroy;
|
---|
232 | begin
|
---|
233 | {$ifdef os2}
|
---|
234 | DosCloseMuxWaitSem( _Handle );
|
---|
235 | FreeMem( _PSemaphoreArray, Sizeof( SEMRECORD ) * _SemaphoreCount );
|
---|
236 | {$else}
|
---|
237 | FreeMem( _PSemaphoreArray, Sizeof( THandle ) * _SemaphoreCount );
|
---|
238 | {$endif}
|
---|
239 | end;
|
---|
240 |
|
---|
241 | Function TMultiWaitSemaphore.Wait: TEventSemaphore;
|
---|
242 | var
|
---|
243 | WhichSem: LongWord;
|
---|
244 | {$ifdef win32}
|
---|
245 | WaitAll: BOOL;
|
---|
246 | {$endif}
|
---|
247 | begin
|
---|
248 | {$ifdef os2}
|
---|
249 | DosWaitMuxWaitSem( _Handle, SEM_INDEFINITE_WAIT, WhichSem );
|
---|
250 | Result:= TEventSemaphore( WhichSem );
|
---|
251 | {$else}
|
---|
252 | WaitAll:= ( _WaitType = wtAll );
|
---|
253 |
|
---|
254 | WhichSem:=
|
---|
255 | WaitForMultipleObjects( _SemaphoreCount,
|
---|
256 | _PSemaphoreHandleArray,
|
---|
257 | WaitAll,
|
---|
258 | INFINITE )
|
---|
259 | - WAIT_OBJECT_0;
|
---|
260 | Result:= _PSemaphoreArray^[ WhichSem ];
|
---|
261 | {$endif}
|
---|
262 |
|
---|
263 | end;
|
---|
264 |
|
---|
265 | constructor TMutex.Create;
|
---|
266 | begin
|
---|
267 | {$ifdef os2}
|
---|
268 | DosCreateMutexSem( nil, _Handle, 0, false );
|
---|
269 | {$else}
|
---|
270 | _Handle:= CreateMutex( nil, false, nil );
|
---|
271 | {$endif}
|
---|
272 | end;
|
---|
273 |
|
---|
274 | constructor TMutex.CreateNamed( const Name: string );
|
---|
275 | {$ifdef os2}
|
---|
276 | var
|
---|
277 | CName: Cstring;
|
---|
278 | {$endif}
|
---|
279 | begin
|
---|
280 | {$ifdef os2}
|
---|
281 | CName := Name;
|
---|
282 | DosCreateMutexSem( CName, _Handle, 0, false );
|
---|
283 | {$else}
|
---|
284 | _Handle:= CreateMutex( nil, false, PChar( Name ) );
|
---|
285 | {$endif}
|
---|
286 | end;
|
---|
287 |
|
---|
288 | destructor TMutex.Destroy;
|
---|
289 | begin
|
---|
290 | {$ifdef os2}
|
---|
291 | DosCloseMutexSem( _Handle );
|
---|
292 | {$else}
|
---|
293 | CloseHandle( _Handle );
|
---|
294 | {$endif}
|
---|
295 | inherited Destroy;
|
---|
296 | end;
|
---|
297 |
|
---|
298 | procedure TMutex.Get;
|
---|
299 | begin
|
---|
300 | {$ifdef os2}
|
---|
301 | DosRequestMutexSem( _Handle, SEM_INDEFINITE_WAIT );
|
---|
302 | {$else}
|
---|
303 | WaitForSingleObject( _Handle, INFINITE );
|
---|
304 | {$endif}
|
---|
305 | end;
|
---|
306 |
|
---|
307 | procedure TMutex.Release;
|
---|
308 | begin
|
---|
309 | {$ifdef os2}
|
---|
310 | DosReleaseMutexSem( _Handle );
|
---|
311 | {$else}
|
---|
312 | ReleaseMutex( _Handle );
|
---|
313 | {$endif}
|
---|
314 | end;
|
---|
315 |
|
---|
316 | Initialization
|
---|
317 | End.
|
---|
318 |
|
---|