151 lines
3.4 KiB
ObjectPascal
151 lines
3.4 KiB
ObjectPascal
unit Myc.Core.Futures;
|
|
|
|
interface
|
|
|
|
uses
|
|
System.SysUtils,
|
|
Myc.Signals,
|
|
Myc.TaskManager,
|
|
Myc.Futures;
|
|
|
|
type
|
|
TMycFuture<T> = class abstract(TInterfacedObject, TFuture<T>.IFuture)
|
|
protected
|
|
function GetValue: T; virtual; abstract;
|
|
function GetDone: TState; virtual; abstract;
|
|
public
|
|
procedure BeforeDestruction; override;
|
|
end;
|
|
|
|
TMycNullFuture<T> = class(TMycFuture<T>)
|
|
private
|
|
FValue: T;
|
|
protected
|
|
function GetValue: T; override;
|
|
function GetDone: TState; override;
|
|
public
|
|
constructor Create(const AValue: T);
|
|
end;
|
|
|
|
TMycGateFuncFuture<T> = class(TMycFuture<T>)
|
|
private
|
|
FDone: TState;
|
|
FResult: T;
|
|
protected
|
|
function GetValue: T; override;
|
|
function GetDone: TState; override;
|
|
public
|
|
constructor Create(const ATaskManager: TTaskManager; const AGate: TState.IState; AProc: TFunc<T>);
|
|
destructor Destroy; override;
|
|
end;
|
|
|
|
TMycFutureManaged<T> = class(TMycFuture<T>)
|
|
private
|
|
FFuture: TFuture<T>.IFuture;
|
|
protected
|
|
function GetValue: T; override;
|
|
function GetDone: TState; override;
|
|
public
|
|
constructor Create(const AFuture: TFuture<T>.IFuture);
|
|
destructor Destroy; override;
|
|
end;
|
|
|
|
implementation
|
|
|
|
{ TMycFuture<T> }
|
|
|
|
procedure TMycFuture<T>.BeforeDestruction;
|
|
begin
|
|
inherited;
|
|
Assert(GetDone.IsSet, 'Trying to destroy an unfinished future');
|
|
end;
|
|
|
|
constructor TMycNullFuture<T>.Create(const AValue: T);
|
|
begin
|
|
inherited Create;
|
|
FValue := AValue;
|
|
end;
|
|
|
|
{ TMycNullFuture<T> }
|
|
|
|
function TMycNullFuture<T>.GetDone: TState;
|
|
begin
|
|
Result := TState.Null;
|
|
end;
|
|
|
|
function TMycNullFuture<T>.GetValue: T;
|
|
begin
|
|
Result := FValue;
|
|
end;
|
|
|
|
{ TMycGateFuncFuture<T> }
|
|
|
|
constructor TMycGateFuncFuture<T>.Create(const ATaskManager: TTaskManager; const AGate: TState.IState; AProc: TFunc<T>);
|
|
begin
|
|
inherited Create;
|
|
|
|
// Subscribe the job execution to AGate.
|
|
// The job will run when AGate notifies the subscriber returned by Run.
|
|
FDone :=
|
|
ATaskManager.RunTask(
|
|
AGate,
|
|
function: TState
|
|
begin
|
|
try
|
|
Self.FResult := AProc();
|
|
except
|
|
Self.FResult := Default(T); // Set result to Default(T) on error
|
|
raise; // Re-raise for TaskFactory to handle
|
|
end;
|
|
end
|
|
);
|
|
end;
|
|
|
|
destructor TMycGateFuncFuture<T>.Destroy;
|
|
begin
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TMycGateFuncFuture<T>.GetDone: TState;
|
|
begin
|
|
Result := FDone;
|
|
end;
|
|
|
|
function TMycGateFuncFuture<T>.GetValue: T;
|
|
begin
|
|
Assert(FDone.IsSet, 'Result is not yet available.');
|
|
Result := FResult;
|
|
end;
|
|
|
|
{ TMycFutureManaged<T> }
|
|
|
|
constructor TMycFutureManaged<T>.Create(const AFuture: TFuture<T>.IFuture);
|
|
begin
|
|
inherited Create;
|
|
FFuture := AFuture;
|
|
end;
|
|
|
|
destructor TMycFutureManaged<T>.Destroy;
|
|
begin
|
|
if GetTypeKind(T) = tkClass then
|
|
begin
|
|
var val := GetValue;
|
|
var obj := TObject(PPointer(@val)^);
|
|
if obj <> nil then
|
|
obj.Free;
|
|
end;
|
|
inherited;
|
|
end;
|
|
|
|
function TMycFutureManaged<T>.GetDone: TState;
|
|
begin
|
|
Result := FFuture.Done;
|
|
end;
|
|
|
|
function TMycFutureManaged<T>.GetValue: T;
|
|
begin
|
|
Result := FFuture.Value;
|
|
end;
|
|
|
|
end.
|