unit Myc.TaskManager; interface uses System.SysUtils, Myc.Signals; type TTaskManager = record type IMycTaskManager = interface procedure RunTask(const Gate: TState; const Proc: TProc); procedure WaitFor(const State: TState); end; private FTaskManager: IMycTaskManager; public constructor Create(const ATaskManager: IMycTaskManager); class operator Implicit(const A: IMycTaskManager): TTaskManager; overload; class operator Implicit(const A: TTaskManager): IMycTaskManager; overload; // Run a task when the gate is opened. procedure RunTask(const Gate: TState; const Proc: TProc); inline; // Waits for the operation associated with State to complete. // Must not be called from a worker thread of this factory. // After waiting, or if the state is already set, any first stored exception // from any worker thread of this factory will be re-raised in the calling (main) thread. // Raises ETaskException if called from within a worker thread. procedure WaitFor(const State: TState); inline; end; var TaskManager: TTaskManager; procedure SetupTaskManagerMock; implementation uses System.Generics.Collections, Myc.Core.Tasks; type TMycExecMock = class(TInterfacedObject, TSignal.ISubscriber) private FProc: TProc; public constructor Create(const AProc: TProc); function Notify: Boolean; end; TMycTaskManagerMock = class(TInterfacedObject, TTaskManager.IMycTaskManager) public // IMycTaskManager procedure RunTask(const Gate: TState; const Proc: TProc); procedure WaitFor(const State: TState); constructor Create; end; { TMycExecMock } constructor TMycExecMock.Create(const AProc: TProc); begin inherited Create; FProc := AProc; end; function TMycExecMock.Notify: Boolean; begin Result := Assigned(FProc); if Result then begin FProc(); FProc := nil; end; end; { TMycTaskManagerMock } constructor TMycTaskManagerMock.Create; begin inherited Create; end; procedure TMycTaskManagerMock.RunTask(const Gate: TState; const Proc: TProc); begin Gate.Signal.Subscribe(TMycExecMock.Create(Proc)); end; procedure TMycTaskManagerMock.WaitFor(const State: TState); begin Assert(State.IsSet); end; procedure SetupTaskManagerMock; begin TaskManager.Create(TMycTaskManagerMock.Create); end; constructor TTaskManager.Create(const ATaskManager: IMycTaskManager); begin FTaskManager := ATaskManager; end; procedure TTaskManager.RunTask(const Gate: TState; const Proc: TProc); begin FTaskManager.RunTask(Gate, Proc); end; procedure TTaskManager.WaitFor(const State: TState); begin FTaskManager.WaitFor(State); end; class operator TTaskManager.Implicit(const A: IMycTaskManager): TTaskManager; begin Result.Create(A); end; class operator TTaskManager.Implicit(const A: TTaskManager): IMycTaskManager; begin Result := A.FTaskManager; end; end.