Browse Source

* API to share JOB objects between threads (if browser allows)

Michaël Van Canneyt 5 months ago
parent
commit
637fa74c5c

+ 2 - 0
packages/wasm-job/fpmake.pp

@@ -30,6 +30,8 @@ begin
     T.Dependencies.AddUnit('job.shared');
     T.Dependencies.AddUnit('job.shared');
     T:=P.Targets.AddUnit('job.js.pas',[wasm32],AllOSes);
     T:=P.Targets.AddUnit('job.js.pas',[wasm32],AllOSes);
     T.Dependencies.AddUnit('job.shared');
     T.Dependencies.AddUnit('job.shared');
+    T:=P.Targets.AddUnit('job.threading.pas',[wasm32],AllOSes);
+    T.Dependencies.AddUnit('job.js');
     P.NamespaceMap:='namespaces.lst';
     P.NamespaceMap:='namespaces.lst';
 {$ifndef ALLPACKAGES}
 {$ifndef ALLPACKAGES}
     Run;
     Run;

+ 3 - 0
packages/wasm-job/namespaced/Wasm.Job.Threading.pas

@@ -0,0 +1,3 @@
+{$DEFINE FPC_DOTTEDUNITS}
+unit Wasm.Job.Threading;
+{$i job.threading.pas}

+ 1 - 0
packages/wasm-job/namespaces.lst

@@ -1,5 +1,6 @@
 src/job.shared.pas=namespaced/Wasm.Job.Shared.pas
 src/job.shared.pas=namespaced/Wasm.Job.Shared.pas
 src/job.js.pas=namespaced/Wasm.Job.Js.pas
 src/job.js.pas=namespaced/Wasm.Job.Js.pas
 src/job.stub.pas=namespaced/Wasm.Job.Stub.pas
 src/job.stub.pas=namespaced/Wasm.Job.Stub.pas
+src/job.threading.pas=namespaced/Wasm.Job.Threading.pas
 {s*:src/}=namespaced/
 {s*:src/}=namespaced/
 {i+:src/}
 {i+:src/}

+ 23 - 1
packages/wasm-job/src/job.js.pas

@@ -300,6 +300,7 @@ type
     procedure WriteJSPropertyValue(const aName: UTF8String; Value: TJOB_JSValue); virtual;
     procedure WriteJSPropertyValue(const aName: UTF8String; Value: TJOB_JSValue); virtual;
     procedure WriteJSPropertyVariant(const aName: UTF8String; const Value: Variant); virtual;
     procedure WriteJSPropertyVariant(const aName: UTF8String; const Value: Variant); virtual;
     procedure WriteJSPropertyMethod(const aName: UTF8String; const Value: TMethod); virtual;
     procedure WriteJSPropertyMethod(const aName: UTF8String; const Value: TMethod); virtual;
+    procedure ShareObject(aThreadID : TThreadID);
     // create a new object using the new-operator
     // create a new object using the new-operator
     function NewJSObject(Const Args: Array of const; aResultClass: TJSObjectClass): TJSObject; virtual;
     function NewJSObject(Const Args: Array of const; aResultClass: TJSObjectClass): TJSObject; virtual;
     procedure ShowAsDebug(Const aMessage : string);
     procedure ShowAsDebug(Const aMessage : string);
@@ -405,6 +406,7 @@ type
     procedure WriteJSPropertyMethod(const aName: UTF8String; const Value: TMethod); virtual;
     procedure WriteJSPropertyMethod(const aName: UTF8String; const Value: TMethod); virtual;
     // create a new object using the new-operator
     // create a new object using the new-operator
     function NewJSObject(Const Args: Array of const; aResultClass: TJSObjectClass): TJSObject; virtual;
     function NewJSObject(Const Args: Array of const; aResultClass: TJSObjectClass): TJSObject; virtual;
+    procedure ShareObject(aThreadID : TThreadID);
     // JS members
     // JS members
     function getOwnPropertyNames(const Obj: IJSObject): TUnicodeStringDynArray;
     function getOwnPropertyNames(const Obj: IJSObject): TUnicodeStringDynArray;
     function getPrototypeOf(const Obj: IJSObject): IJSObject;
     function getPrototypeOf(const Obj: IJSObject): IJSObject;
@@ -1492,11 +1494,12 @@ Procedure ShowLiveObjects(const Message: String);
 Type
 Type
   TJobCallbackErrorEvent = Procedure (E : Exception; M : TMethod; H : TJobCallbackHelper; Var ReRaise : Boolean) of Object;
   TJobCallbackErrorEvent = Procedure (E : Exception; M : TMethod; H : TJobCallbackHelper; Var ReRaise : Boolean) of Object;
   TJobCallBackErrorCallback = Procedure (E : Exception; M : TMethod; H : TJobCallbackHelper; Var ReRaise : Boolean);
   TJobCallBackErrorCallback = Procedure (E : Exception; M : TMethod; H : TJobCallbackHelper; Var ReRaise : Boolean);
+  TJobShareObjectCallback = Procedure (aObjID: TJOBObjectID; aThreadID: TThreadID; out aResult: TJOBResult);
 
 
 var
 var
   JobCallbackErrorHandler : TJobCallbackErrorEvent;
   JobCallbackErrorHandler : TJobCallbackErrorEvent;
   JobCallbackErrorCallBack : TJobCallBackErrorCallback;
   JobCallbackErrorCallBack : TJobCallBackErrorCallback;
-
+  JobShareObjectCallBack : TJobShareObjectCallback;
 
 
 implementation
 implementation
 
 
@@ -1552,6 +1555,13 @@ begin
     Writeln(Message,': ',TJOB_Double(aObject).AsString);
     Writeln(Message,': ',TJOB_Double(aObject).AsString);
 end;
 end;
 
 
+Procedure NoShareSupport(aObjID: TJOBObjectID; aThreadID: TThreadID; out aResult: TJOBResult);
+
+begin
+  aResult:=0;
+  Raise EJSObject.CreateFmt('Cannot share object %d with thread %d, recompile your program with unit job.threading included in the uses clause.',[aObjId,PtrInt(aThreadId)]);
+end;
+
 procedure ShowLiveObjects(const Message: String);
 procedure ShowLiveObjects(const Message: String);
 var
 var
   msg : Rawbytestring;
   msg : Rawbytestring;
@@ -5063,6 +5073,17 @@ begin
   Result:=InvokeJSObjectResult('',Args,aResultClass,jiNew);
   Result:=InvokeJSObjectResult('',Args,aResultClass,jiNew);
 end;
 end;
 
 
+procedure TJSObject.ShareObject(aThreadID: TThreadID);
+var
+  Res : TJOBResult;
+begin
+  if not assigned(JobShareObjectCallBack) then
+    JobShareObjectCallBack:=@NoShareSupport;
+  JobShareObjectCallBack(JOBObjectID,aThreadID,Res);
+  if (Res<>JOBResult_Success) then
+    Raise EJSObject.CreateFmt('Failed to share object %d with thread %d',[JOBObjectID,PtrInt(aThreadID)]);
+end;
+
 function TJSObject.getOwnPropertyNames(const Obj: IJSObject
 function TJSObject.getOwnPropertyNames(const Obj: IJSObject
   ): TUnicodeStringDynArray;
   ): TUnicodeStringDynArray;
 begin
 begin
@@ -5132,6 +5153,7 @@ end;
 exports JOBCallback;
 exports JOBCallback;
 
 
 initialization
 initialization
+  JobShareObjectCallBack:=@NoShareSupport;
   JSObject:=TJSObject.JOBCreateGlobal('Object') as IJSObject;
   JSObject:=TJSObject.JOBCreateGlobal('Object') as IJSObject;
   JSDate:=TJSDate.JOBCreateGlobal('Date') as IJSDate;
   JSDate:=TJSDate.JOBCreateGlobal('Date') as IJSDate;
   JSJSON:=TJSJSON.JOBCreateGlobal('JSON') as IJSJSON;
   JSJSON:=TJSJSON.JOBCreateGlobal('JSON') as IJSJSON;

+ 1 - 0
packages/wasm-job/src/job.shared.pas

@@ -70,6 +70,7 @@ const
   JOBFn_SetMemFromArray = 'set_mem_from_object';
   JOBFn_SetMemFromArray = 'set_mem_from_object';
   JOBFn_SetArrayFromMem = 'set_object_from_mem';
   JOBFn_SetArrayFromMem = 'set_object_from_mem';
   JOBFn_DebugObject = 'debug_object';
   JOBFn_DebugObject = 'debug_object';
+  JOBFn_ShareObject = 'share_object';
 
 
   JOBArgUndefined = 0;
   JOBArgUndefined = 0;
   JOBArgLongint = 1;
   JOBArgLongint = 1;

+ 33 - 0
packages/wasm-job/src/job.threading.pas

@@ -0,0 +1,33 @@
+{$IFNDEF FPC_DOTTEDUNITS}
+unit job.threading;
+{$ENDIF}
+
+{$mode ObjFPC}{$H+}
+
+interface
+
+uses
+  {$IFDEF FPC_DOTTEDUNITS}
+  Wasm.Job.Js, Wasm.Job.Shared;
+  {$ELSE}
+  job.js, job.shared;
+  {$ENDIF}
+
+// imported functions from browser
+function __job_share_object(
+  ObjID: TJOBObjectID; // Object to share
+  ThreadID: TThreadID // Thread to share with. Set to 0 to share with all objects
+): TJOBResult; external JOBExportName name JOBFn_ShareObject;
+
+implementation
+
+Procedure ShareJobObject(aObjID: TJOBObjectID; aThreadID: TThreadID; out aResult: TJOBResult);
+
+begin
+  aResult:=__job_share_object(aObjId,aThreadId);
+end;
+
+initialization
+  JobShareObjectCallBack:=@ShareJobObject;
+end.
+