Files
MycLib/Src/Myc.Futures.pas
Michael Schimmel c4d8607d17 TMutable
2025-06-06 01:22:25 +02:00

129 lines
3.2 KiB
ObjectPascal

unit Myc.Futures;
interface
uses
System.SysUtils,
Myc.Signals,
Myc.TaskManager;
type
// Represents the eventual result of an asynchronous operation.
TFuture<T> = record
type
IFuture = interface
{$REGION 'property access'}
function GetResult: T;
function GetDone: TState;
{$ENDREGION}
// Provides access to the computed result.
property Result: T read GetResult;
// Provides access to the completion state.
property Done: TState read GetDone;
end;
{$REGION 'private'}
strict private
class var
FNull: IFuture;
class constructor CreateClass;
class destructor DestroyClass;
private
FFuture: IFuture;
function GetDone: TState; inline;
function GetResult: T; inline;
{$ENDREGION}
public
constructor Create(const AFuture: IFuture);
class operator Initialize(out Dest: TFuture<T>);
class operator Implicit(const A: IFuture): TFuture<T>; overload;
class operator Implicit(const A: TFuture<T>): IFuture; overload;
class function Construct(const Proc: TFunc<T>): TFuture<T>; overload; static;
class function Construct(const Gate: TState.IState; const Proc: TFunc<T>): TFuture<T>; overload; static;
class property Null: IFuture read FNull;
function Chain<S>(const Proc: TFunc<T, S>): TFuture<S>;
function WaitFor: T;
property Done: TState read GetDone;
property Result: T read GetResult;
end;
implementation
uses
Myc.Core.Futures,
Myc.Core.Tasks;
constructor TFuture<T>.Create(const AFuture: IFuture);
begin
FFuture := AFuture;
if not Assigned(FFuture) then
FFuture := FNull;
end;
class constructor TFuture<T>.CreateClass;
begin
TMycTaskFactory.AquireTaskManager;
FNull := TMycNullFuture<T>.Create;
end;
class destructor TFuture<T>.DestroyClass;
begin
TMycTaskFactory.ReleaseTaskManager;
end;
function TFuture<T>.Chain<S>(const Proc: TFunc<T, S>): TFuture<S>;
begin
var Cap := FFuture;
Result := TFuture<S>.Construct(FFuture.Done, function: S begin Result := Proc(Cap.Result); end);
end;
class function TFuture<T>.Construct(const Proc: TFunc<T>): TFuture<T>;
begin
Result := TMycGateFuncFuture<T>.Create(TaskManager, nil, Proc);
end;
class function TFuture<T>.Construct(const Gate: TState.IState; const Proc: TFunc<T>): TFuture<T>;
begin
Result := TMycGateFuncFuture<T>.Create(TaskManager, Gate, Proc);
end;
function TFuture<T>.GetDone: TState;
begin
Result := FFuture.Done;
end;
function TFuture<T>.GetResult: T;
begin
Result := FFuture.Result;
end;
function TFuture<T>.WaitFor: T;
begin
TaskManager.WaitFor(FFuture.Done);
Result := FFuture.Result;
end;
class operator TFuture<T>.Implicit(const A: IFuture): TFuture<T>;
begin
Result.Create(A);
end;
class operator TFuture<T>.Implicit(const A: TFuture<T>): IFuture;
begin
Result := A.FFuture;
end;
class operator TFuture<T>.Initialize(out Dest: TFuture<T>);
begin
Dest.FFuture := FNull;
end;
end.