[fpc-devel] Why FreeBSD sem_init() works different to Linux?
Ewald
ewald at yellowcouch.org
Wed Feb 6 23:16:02 CET 2013
Hello,
You can use some structure to lock an integer. `Some structure` can for
example be a mutex, a critical section, some busy waiting loop based on
CMPXCH, etc... Say that you lock the integer by calling `Lock;` and you
unlock it by calling `UnLock;`. Then you can define a class TSemaphore
like this:
===> Code Begin <===
Type
TSemaphore = Class
Private
DaValue: Integer;
Lock: TLockType;
Public
Constructor Create; // sem_init
Function GetValue: Integer; // sem_getvalue
Procedure Post; // sem_post
Function TryWait: Boolean; //sem_trywait
End;
Constructor TSemaphore.Create;
Begin
inherited Create;
DaValue:= 0;
//Initialize lock here to unlocked state.
End;
Function TSemaphore.GetValue;
Begin
Lock;
Result:= DaValue;
UnLock;
End;
Procedure TSemaphore.Post;
Begin
Lock;
DaValue+= 1;
UnLock;
End;
// True if the semaphore is hereby decremented; false otherwise
Function TSemaphore.TryWait: Boolean;
Begin
Lock;
If DaValue > 0 Then
Begin
DaValue-= 1;
Result:= True;
End Else
Result:= False;
UnLock;
End;
//True if this function returned immediately, false otherwise.
Function TSemaphore.Wait: Boolean;
Begin
Result:= True;
While True Do
Begin
Lock;
If DaValue > 0 Then
Begin
DaValue-= 1;
Break;
End;
Result:= False;
UnLock;
End;
End;
===> Code End <===
The only function missing is sem_timedwait, but this could easily be
implemented by combining `nanosleep`, `trywait` and `timeofday`.
NOTE: The above code is not tested, it more of a thing which I just
wrote, so you will probably find some syntax errors and possible race
conditions; altough I doubt the latter.
Concerning the locking mechanism, you can uses mutex(en/es/ii) or you
can do this by a busy waiting loop with an integer (of course there are
other possibilities). To elaborate on the latter a bit more:
* TLockType = Integer;
* Initialization: `Lock:= 0;`
* Lock & unlock:
===> Code Begin <===
Procedure WaitLockVar(var aLock: Integer);
Begin
Repeat
Until InterLockedCompareExchange(aLock, 1, 0) = 0;
End;
Procedure UnlockVar(var aLock: Integer);
Begin
InterlockedExchange(aLock, 0);
End;
===> Code End <===
This last code is tested and works.
Hope it is of any use.
Once upon a time, on 02/06/2013 08:24 PM to be precise, Graeme
Geldenhuys said:
>
> It case I'm overlooking something critical, has anybody else done
> something like this. If so, anybody willing to share that code - saving
> me some time in developing, unit testing and debugging my own Object
> Pascal based semaphore.
>
--
Ewald
More information about the fpc-devel
mailing list