unit Myc.Core.Future; interface uses System.SysUtils, Myc.Signals, Myc.TaskManager, Myc.Futures; type TMycFuture = class abstract(TInterfacedObject, TFuture.IFuture) protected function GetValue: T; virtual; abstract; function GetDone: TState; virtual; abstract; public procedure BeforeDestruction; override; end; TMycNullFuture = class(TMycFuture) private FValue: T; protected function GetValue: T; override; function GetDone: TState; override; public constructor Create(const AValue: T); end; TMycGateFuncFuture = class(TMycFuture) 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); destructor Destroy; override; end; TMycFutureManaged = class(TMycFuture) private FFuture: TFuture.IFuture; protected function GetValue: T; override; function GetDone: TState; override; public constructor Create(const AFuture: TFuture.IFuture); destructor Destroy; override; end; implementation { TMycFuture } procedure TMycFuture.BeforeDestruction; begin inherited; Assert(GetDone.IsSet, 'Trying to destroy an unfinished future'); end; constructor TMycNullFuture.Create(const AValue: T); begin inherited Create; FValue := AValue; end; { TMycNullFuture } function TMycNullFuture.GetDone: TState; begin Result := TState.Null; end; function TMycNullFuture.GetValue: T; begin Result := FValue; end; { TMycGateFuncFuture } constructor TMycGateFuncFuture.Create(const ATaskManager: TTaskManager; const AGate: TState.IState; AProc: TFunc); 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.Destroy; begin inherited Destroy; end; function TMycGateFuncFuture.GetDone: TState; begin Result := FDone; end; function TMycGateFuncFuture.GetValue: T; begin Assert(FDone.IsSet, 'Result is not yet available.'); Result := FResult; end; { TMycFutureManaged } constructor TMycFutureManaged.Create(const AFuture: TFuture.IFuture); begin inherited Create; FFuture := AFuture; end; destructor TMycFutureManaged.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.GetDone: TState; begin Result := FFuture.Done; end; function TMycFutureManaged.GetValue: T; begin Result := FFuture.Value; end; end.