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