Files
MycLib/Src/Myc.Core.Futures.pas
T
Michael Schimmel 556690fa5e Refactoring
2025-06-03 18:20:02 +02:00

96 lines
2.4 KiB
ObjectPascal

unit Myc.Core.Futures;
interface
uses
System.SysUtils,
Myc.Signals, Myc.TaskManager, Myc.Futures;
type
TMycFuture<T> = class abstract( TInterfacedObject, IMycFuture<T> )
protected
function GetResult: T; virtual; abstract;
function GetDone: TState; virtual; abstract;
end;
TMycNullFuture<T> = class( TMycFuture<T> )
protected
function GetResult: T; override;
function GetDone: TState; override;
end;
TMycGateFuncFuture<T> = class( TMycFuture<T> )
private
FInit: TState.TSubscription;
FDone: IMycLatch;
FResult: T;
protected
function GetResult: T; override;
function GetDone: TState; override;
public
constructor Create( const ATaskManager: IMycTaskManager; const AGate: IMycState; AProc: TFunc<T> );
destructor Destroy; override;
end;
implementation
{ TMycNullFuture<T> }
function TMycNullFuture<T>.GetDone: TState;
begin
Result := TState.Null;
end;
function TMycNullFuture<T>.GetResult: T;
begin
Result := Default ( T );
end;
{ TMycGateFuncFuture<T> }
constructor TMycGateFuncFuture<T>.Create( const ATaskManager: IMycTaskManager; const AGate: IMycState; AProc: TFunc<T> );
begin
inherited Create;
FDone := TLatch.Construct( 1 );
// Subscribe the job execution to AGate.
// The job will run when AGate notifies the subscriber returned by Run.
FInit := ATaskManager.CreateTask(
AGate,
procedure
begin
try
try
Self.FResult := AProc( );
except
Self.FResult := Default ( T ); // Set result to Default(T) on error
raise; // Re-raise for TaskFactory to handle
end;
finally
Self.FDone.Notify; // Signal that this future is done (successfully or with error)
end;
end );
end;
destructor TMycGateFuncFuture<T>.Destroy;
begin
Assert( FDone.State.IsSet );
FInit.Unsubscribe;
inherited Destroy;
end;
function TMycGateFuncFuture<T>.GetDone: TState;
begin
Result := FDone.State;
end;
function TMycGateFuncFuture<T>.GetResult: T;
begin
Assert( FDone.State.IsSet, 'Result is not yet available.' );
Result := FResult;
end;
end.