Future<T> helper record

This commit is contained in:
Michael Schimmel
2025-06-02 14:27:00 +02:00
parent 48f4c945ce
commit e1beb7ff5b
6 changed files with 62 additions and 21 deletions
+1 -7
View File
@@ -41,13 +41,6 @@ type
// will be re-raised in the calling (main) thread.
procedure Teardown;
// Waits for the operation associated with State to complete.
// Must not be called from a worker thread of this factory.
// After waiting, or if the state is already set, any first stored exception
// from any worker thread of this factory will be re-raised in the calling (main) thread.
// Raises ETaskException if called from within a worker thread.
procedure WaitFor(State: IMycState);
// Gets the number of worker threads.
property ThreadCount: Integer read GetThreadCount;
end;
@@ -89,6 +82,7 @@ type
function InMainThread: Boolean;
function InWorkerThread: Boolean;
// Initialize global TaskManager
class procedure AquireTaskManager;
class procedure ReleaseTaskManager;
end;
+48 -10
View File
@@ -22,14 +22,26 @@ type
Future<T> = record
strict private
FFuture: IMycFuture<T>;
function GetDone: IMycState; inline;
function GetResult: T; inline;
class constructor CreateClass;
class destructor DestroyClass;
constructor Create(const AFuture: IMycFuture<T>);
public
class function Construct(const Proc: TFunc<T>): Future<T>; overload; static;
class function Construct(const Gate: IMycState; const Proc: TFunc<T>): Future<T>; overload; static;
function Chain<S>(const Proc: TFunc<T, S>): Future<S>;
public
constructor Create(const AFuture: IMycFuture<T>);
class operator Implicit(const A: IMycFuture<T>): Future<T>; overload;
class operator Implicit(const A: Future<T>): IMycFuture<T>; overload;
class function Construct(const Proc: TFunc<T>): IMycFuture<T>; overload; static;
class function Construct(const Gate: IMycState; const Proc: TFunc<T>): IMycFuture<T>; overload; static;
function Chain<S>(const Proc: TFunc<T, S>): IMycFuture<S>;
function WaitFor: T;
property Done: IMycState read GetDone;
property Result: T read GetResult;
end;
implementation
@@ -52,7 +64,7 @@ begin
TMycTaskFactory.ReleaseTaskManager;
end;
function Future<T>.Chain<S>(const Proc: TFunc<T, S>): Future<S>;
function Future<T>.Chain<S>(const Proc: TFunc<T, S>): IMycFuture<S>;
begin
var Cap := FFuture;
@@ -63,14 +75,40 @@ begin
end );
end;
class function Future<T>.Construct(const Proc: TFunc<T>): Future<T>;
class function Future<T>.Construct(const Proc: TFunc<T>): IMycFuture<T>;
begin
Result.Create( TMycInitStateFuncFuture<T>.Create( TaskManager, nil, Proc ) );
Result := TMycInitStateFuncFuture<T>.Create( TaskManager, nil, Proc );
end;
class function Future<T>.Construct(const Gate: IMycState; const Proc: TFunc<T>): Future<T>;
class function Future<T>.Construct(const Gate: IMycState; const Proc: TFunc<T>): IMycFuture<T>;
begin
Result.Create( TMycInitStateFuncFuture<T>.Create( TaskManager, Gate, Proc ) );
Result := TMycInitStateFuncFuture<T>.Create( TaskManager, Gate, Proc );
end;
function Future<T>.GetDone: IMycState;
begin
Result := FFuture.Done;
end;
function Future<T>.GetResult: T;
begin
Result := FFuture.Result;
end;
function Future<T>.WaitFor: T;
begin
TaskManager.WaitFor( FFuture.Done );
Result := FFuture.Result;
end;
class operator Future<T>.Implicit(const A: IMycFuture<T>): Future<T>;
begin
Result.Create( A );
end;
class operator Future<T>.Implicit(const A: Future<T>): IMycFuture<T>;
begin
Result := A.FFuture;
end;
end.
+7
View File
@@ -9,6 +9,13 @@ uses
type
IMycTaskManager = interface
function CreateTask( const Gate: IMycState; const Proc: TProc ): TMycSubscription;
// Waits for the operation associated with State to complete.
// Must not be called from a worker thread of this factory.
// After waiting, or if the state is already set, any first stored exception
// from any worker thread of this factory will be re-raised in the calling (main) thread.
// Raises ETaskException if called from within a worker thread.
procedure WaitFor(State: IMycState);
end;
var
+3 -2
View File
@@ -24,10 +24,11 @@ uses
TestTasks in 'TestTasks.pas',
TestSignals_Dirty in 'TestSignals_Dirty.pas',
Myc.Futures in '..\Src\Myc.Futures.pas',
TestFutures in 'TestFutures.pas',
TestCoreFutures in 'TestCoreFutures.pas',
Myc.TaskManager in '..\Src\Myc.TaskManager.pas',
Myc.Core.Futures in '..\Src\Myc.Core.Futures.pas',
Myc.Core.Signals in '..\Src\Myc.Core.Signals.pas';
Myc.Core.Signals in '..\Src\Myc.Core.Signals.pas',
TestFutures in 'TestFutures.pas';
{ keep comment here to protect the following conditional from being removed by the IDE when adding a unit }
{$IFNDEF TESTINSIGHT}
+2 -1
View File
@@ -123,10 +123,11 @@ $(PostBuildEvent)]]></PostBuildEvent>
<DCCReference Include="TestTasks.pas"/>
<DCCReference Include="TestSignals_Dirty.pas"/>
<DCCReference Include="..\Src\Myc.Futures.pas"/>
<DCCReference Include="TestFutures.pas"/>
<DCCReference Include="TestCoreFutures.pas"/>
<DCCReference Include="..\Src\Myc.TaskManager.pas"/>
<DCCReference Include="..\Src\Myc.Core.Futures.pas"/>
<DCCReference Include="..\Src\Myc.Core.Signals.pas"/>
<DCCReference Include="TestFutures.pas"/>
<BuildConfiguration Include="Base">
<Key>Base</Key>
</BuildConfiguration>
@@ -1,4 +1,4 @@
unit TestFutures;
unit TestCoreFutures;
interface