100 lines
2.8 KiB
ObjectPascal
100 lines
2.8 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.
|