81 lines
2.3 KiB
ObjectPascal
81 lines
2.3 KiB
ObjectPascal
unit Myc.Core.Futures;
|
|
|
|
interface
|
|
|
|
uses
|
|
System.SysUtils,
|
|
Myc.Signals, Myc.TaskManager, Myc.Futures;
|
|
|
|
type
|
|
// Abstract base class for IMycFuture<T> implementations.
|
|
TMycFuture<T> = class abstract( TInterfacedObject, IMycFuture<T> )
|
|
protected
|
|
function GetResult: T; virtual; abstract;
|
|
function GetDone: IMycState; virtual; abstract;
|
|
end;
|
|
|
|
// Concrete future implementation triggered by an initial state, executing a TFunc<T>.
|
|
TMycInitStateFuncFuture<T> = class( TMycFuture<T> )
|
|
private
|
|
FInit: TMycSubscription;
|
|
FDone: IMycLatch;
|
|
FResult: T;
|
|
protected
|
|
function GetResult: T; override;
|
|
function GetDone: IMycState; override;
|
|
public
|
|
// Creates a future that executes AProc after AGate is set, using ATaskFactory.
|
|
constructor Create( const ATaskManager: IMycTaskManager; const AGate: IMycState; AProc: TFunc<T> );
|
|
destructor Destroy; override;
|
|
end;
|
|
|
|
implementation
|
|
|
|
{ TMycInitStateFuncFuture<T> }
|
|
|
|
constructor TMycInitStateFuncFuture<T>.Create( const ATaskManager: IMycTaskManager; const AGate: IMycState; AProc: TFunc<T> );
|
|
begin
|
|
inherited Create;
|
|
|
|
FDone := State.CreateLatch( 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 TMycInitStateFuncFuture<T>.Destroy;
|
|
begin
|
|
Assert( FDone.State.IsSet );
|
|
|
|
FInit.Unsubscribe;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TMycInitStateFuncFuture<T>.GetDone: IMycState;
|
|
begin
|
|
Result := FDone.State;
|
|
end;
|
|
|
|
function TMycInitStateFuncFuture<T>.GetResult: T;
|
|
begin
|
|
Assert( FDone.State.IsSet, 'Result is not yet available.' );
|
|
Result := FResult;
|
|
end;
|
|
|
|
end.
|