[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