Browse Source

* Semaphore implementation for wasm

Michaël Van Canneyt 1 week ago
parent
commit
2399700a9a
1 changed files with 47 additions and 3 deletions
  1. 47 3
      packages/fcl-base/src/syncobjs.pp

+ 47 - 3
packages/fcl-base/src/syncobjs.pp

@@ -38,6 +38,9 @@ uses
   {$IFDEF UNIX}
   UnixApi.Types,
   {$ENDIF}
+  {$IFDEF CPUWASM32}
+  Wasm.Semaphore,
+  {$ENDIF}
   System.SysUtils;
   
 {$ELSE FPC_DOTTEDUNITS}
@@ -47,6 +50,9 @@ uses
   {$IFDEF UNIX}
   unixtype,
   {$ENDIF}
+  {$IFDEF CPUWASM32}
+  WasmSem,
+  {$ENDIF}
   sysutils;
 {$ENDIF FPC_DOTTEDUNITS}
 
@@ -192,6 +198,9 @@ type
   TSemaphore = class(THandleObject)
   {$IFDEF UNIX}
      Fsem: TPosixSemaphore;
+  {$ENDIF}
+  {$IFDEF CPUWASM32}
+     FSem : TWasmSemaphore;
   {$ENDIF}
    public
      constructor Create(aUseCOMWait: boolean = false); overload;
@@ -250,6 +259,7 @@ Resourcestring
   SErrNamesNotSupported   = 'Named semaphores are not supported on this platform';
   SErrNoSemaphoreSupport  = 'Semaphores are not supported on this platform';
   SErrInvalidReleaseCount = '%d is not a valid release count, count must be >0';
+  SErrFailedToSignalSemaphore = 'Failed to signal semaphore at count %d';
   SErrMutexNotSupported   = 'Mutexes are not supported on this platform';
   
 { ---------------------------------------------------------------------
@@ -705,9 +715,13 @@ begin
     raise ESyncObjectException.Create(SErrNamesNotSupported);
   if sem_init(@FSem,0,aInitial)<>0 then
     RaiseLastOSError;
-{$ELSE}
+{$ELSE UNIX}
+{$IFDEF CPUWASM32}
+  semaphore_init(FSEM,aInitial,aMaximum);
+{$ELSE CPUWASM32}
   Raise ESyncObjectException.Create(SErrNoSemaphoreSupport);
-{$ENDIF}    
+{$ENDIF CPUWASM32}
+{$ENDIF UNIX}
 {$ENDIF WINDOWS}
 end;
 
@@ -740,7 +754,11 @@ destructor TSemaphore.Destroy;
 begin
 {$IFDEF UNIX}
   sem_destroy(@FSem);
-{$ENDIF}  
+{$ENDIF}
+{$IFDEF CPUWASM32}
+  // If someone is waiting, (s)he'll be notified...
+  semaphore_signal(FSEM);
+{$ENDIF}
   inherited Destroy;
 end;
 
@@ -748,6 +766,10 @@ end;
 
 function TSemaphore.WaitFor(aTimeout: Cardinal = INFINITE): TWaitResult; 
 
+{$IFDEF wasm32}
+var
+  Res : Boolean;
+{$ENDIF}
 
 {$IFDEF UNIX}
 var
@@ -799,8 +821,20 @@ begin
       Result:=wrSignaled
     end;
 {$ELSE UNIX}
+{$IFDEF CPUWASM32}
+  if aTimeout=INFINITE then
+    Res:=semaphore_wait_infinite(FSEM)
+  else
+    Res:=semaphore_wait(FSEM,aTimeOut);
+  if Res then
+    Result:=wrSignaled
+  else
+    Result:=wrTimeout;
+{$ELSE}
   Result:=Inherited WaitFor(aTimeOut);
+{$ENDIF}
 {$ENDIF UNIX}
+
 end;
 
 
@@ -837,6 +871,16 @@ begin
     Dec(aCount);
     end;
 {$ENDIF}
+{$IFDEF CPUWASM32}
+  Result:=0;
+  While aCount>0 do
+    begin
+    if not semaphore_signal(FSem) then
+          raise ESyncObjectException.CreateFmt(SErrFailedToSignalSemaphore, [aCount]);
+    Inc(Result);
+    Dec(aCount);
+    end;
+{$ENDIF}
 end;
 
 {$ENDIF NO_SEMAPHORE_SUPPORT}