Semaphores

Whereas a Mutex may be used to allow only a single instance of your app, a Semaphore can be use to allow a specific number.

Creating semaphores

A Semaphore is created using the windows CreateSemaphore API command.



HANDLE CreateSemaphore(

  LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,// security attributes

  LONG lInitialCount, // initial count

  LONG lMaximumCount, // maximum count

  LPCTSTR lpName // pointer to semaphore-object name

);



Example

HSemaphore := CreateSemaphore(nil, MaximumInstances,

  MaximumInstances,PChar(UniqueName));



Unique name must be a Windows-wide unique identifier, I recommend that you use CompanyName.ProductName, or even a GUID (Press CTRL+SHIFT+G to generate a GUID at design time).



Here is a class wrapper for a SemaPhore, create an instance of the class and use LOCK to use a reserved place and Unlock to release it.



unit Semaphores;



interface

uses

  Windows, SysUtils;



const

  cSemaphoreCannotCreate = 'Cannot create semaphore';



type

  ESemaphoreError = class(Exception);



  TSemaphore = class

  private

    HSemaphore : THandle;

    FLocked : Boolean;

  public

    Constructor Create(UniqueName : string;


         MaximumInstances : Integer); virtual;

    destructor Destroy; override;



    function Lock(aTimeoutMilliseconds : DWord) : Boolean;

    procedure UnLock;



    property Locked: Boolean read FLocked;

  end;



implementation



{ TSemaphore }



constructor TSemaphore.Create(UniqueName: String;

  MaximumInstances: Integer);

begin

  inherited Create;

  FLocked := False;

  HSemaphore := 0;

  HSemaphore := CreateSemaphore(nil,MaximumInstances,MaximumInstances,PChar(UniqueName));



  if HSemaphore = 0 then

    raise ESemaphoreError.Create(cSemaphoreCannotCreate);



end;



destructor TSemaphore.Destroy;

begin

  UnLock;

  inherited;

end;



function TSemaphore.Lock(aTimeoutMilliseconds: DWord): Boolean;

var

  Res : Integer;

begin

  Res := WaitForSingleObject(hSemaphore, aTimeoutMilliseconds);

  Result := (Res in [WAIT_ABANDONED, WAIT_OBJECT_0]);

  if Result then FLocked := True;

end;



procedure TSemaphore.UnLock;

begin

  if not Locked then exit;

  ReleaseSemaphore(hSemaphore,1,nil);

end;



end.


 

Share this article!

Follow us!

Find more helpful articles:

Popular Searches

Add comment

The content of this field is kept private and will not be shown publicly.

More information about formatting options

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.