TaskManager refactoring
This commit is contained in:
+64
-17
@@ -9,23 +9,29 @@ uses
|
||||
type
|
||||
TTaskManager = record
|
||||
type
|
||||
IMycTaskManager = interface
|
||||
ITaskManager = interface
|
||||
procedure CreateThread(const Proc: TProc);
|
||||
procedure RunTask(const Gate: TState; const Proc: TProc);
|
||||
procedure WaitFor(const State: TState);
|
||||
end;
|
||||
private
|
||||
FTaskManager: IMycTaskManager;
|
||||
FTaskManager: ITaskManager;
|
||||
|
||||
public
|
||||
constructor Create(const ATaskManager: IMycTaskManager);
|
||||
class operator Implicit(const A: IMycTaskManager): TTaskManager; overload;
|
||||
class operator Implicit(const A: TTaskManager): IMycTaskManager; overload;
|
||||
constructor Create(const ATaskManager: ITaskManager);
|
||||
class operator Implicit(const A: ITaskManager): TTaskManager; overload;
|
||||
class operator Implicit(const A: TTaskManager): ITaskManager; overload;
|
||||
|
||||
// Creates and starts a new, independent thread executing Proc.
|
||||
// Returns a State to await thread completion.
|
||||
function CreateThread(const Proc: TProc): TState;
|
||||
|
||||
// Run a task when the gate is opened.
|
||||
procedure RunTask(const Gate: TState; const Proc: TProc); inline;
|
||||
// Returns a State to await thread completion.
|
||||
function RunTask(const Gate: TState; const Proc: TFunc<TState>): TState;
|
||||
|
||||
// Waits for the operation associated with State to complete.
|
||||
// Must not be called from a worker thread of this factory.
|
||||
// Must not be called from a task 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.
|
||||
@@ -40,7 +46,6 @@ procedure SetupTaskManagerMock;
|
||||
implementation
|
||||
|
||||
uses
|
||||
System.Generics.Collections,
|
||||
Myc.Core.Tasks;
|
||||
|
||||
type
|
||||
@@ -52,13 +57,12 @@ type
|
||||
function Notify: Boolean;
|
||||
end;
|
||||
|
||||
TMycTaskManagerMock = class(TInterfacedObject, TTaskManager.IMycTaskManager)
|
||||
TMycTaskManagerMock = class(TInterfacedObject, TTaskManager.ITaskManager)
|
||||
public
|
||||
// IMycTaskManager
|
||||
constructor Create;
|
||||
procedure RunTask(const Gate: TState; const Proc: TProc);
|
||||
procedure WaitFor(const State: TState);
|
||||
|
||||
constructor Create;
|
||||
procedure CreateThread(const Proc: TProc);
|
||||
end;
|
||||
|
||||
{ TMycExecMock }
|
||||
@@ -86,6 +90,11 @@ begin
|
||||
inherited Create;
|
||||
end;
|
||||
|
||||
procedure TMycTaskManagerMock.CreateThread(const Proc: TProc);
|
||||
begin
|
||||
Proc();
|
||||
end;
|
||||
|
||||
procedure TMycTaskManagerMock.RunTask(const Gate: TState; const Proc: TProc);
|
||||
begin
|
||||
Gate.Signal.Subscribe(TMycExecMock.Create(Proc));
|
||||
@@ -101,14 +110,52 @@ begin
|
||||
TaskManager.Create(TMycTaskManagerMock.Create);
|
||||
end;
|
||||
|
||||
constructor TTaskManager.Create(const ATaskManager: IMycTaskManager);
|
||||
constructor TTaskManager.Create(const ATaskManager: ITaskManager);
|
||||
begin
|
||||
FTaskManager := ATaskManager;
|
||||
end;
|
||||
|
||||
procedure TTaskManager.RunTask(const Gate: TState; const Proc: TProc);
|
||||
function TTaskManager.CreateThread(const Proc: TProc): TState;
|
||||
begin
|
||||
FTaskManager.RunTask(Gate, Proc);
|
||||
// Create a latch that will be signaled when the proc finishes
|
||||
var done := TLatch.CreateLatch(1);
|
||||
Result := done.State;
|
||||
|
||||
var cProc := Proc; // Capture Proc for the anonymous method
|
||||
FTaskManager.CreateThread(
|
||||
procedure
|
||||
begin
|
||||
try
|
||||
cProc(); // Execute the provided procedure
|
||||
finally
|
||||
cProc := nil; // Clear the captured proc
|
||||
done.Notify; // Signal completion via the latch's Notify method
|
||||
end;
|
||||
end
|
||||
);
|
||||
end;
|
||||
|
||||
function TTaskManager.RunTask(const Gate: TState; const Proc: TFunc<TState>): TState;
|
||||
begin
|
||||
var cProc: TFunc<TState> := Proc;
|
||||
if not Assigned(@cProc) then
|
||||
exit(TState.Null);
|
||||
|
||||
var Done := TLatch.CreateLatch(1);
|
||||
Result := Done.State;
|
||||
|
||||
FTaskManager.RunTask(
|
||||
Gate,
|
||||
procedure
|
||||
begin
|
||||
try
|
||||
cProc.Signal.Subscribe(Done);
|
||||
except
|
||||
Done.Notify;
|
||||
raise;
|
||||
end;
|
||||
end
|
||||
);
|
||||
end;
|
||||
|
||||
procedure TTaskManager.WaitFor(const State: TState);
|
||||
@@ -116,12 +163,12 @@ begin
|
||||
FTaskManager.WaitFor(State);
|
||||
end;
|
||||
|
||||
class operator TTaskManager.Implicit(const A: IMycTaskManager): TTaskManager;
|
||||
class operator TTaskManager.Implicit(const A: ITaskManager): TTaskManager;
|
||||
begin
|
||||
Result.Create(A);
|
||||
end;
|
||||
|
||||
class operator TTaskManager.Implicit(const A: TTaskManager): IMycTaskManager;
|
||||
class operator TTaskManager.Implicit(const A: TTaskManager): ITaskManager;
|
||||
begin
|
||||
Result := A.FTaskManager;
|
||||
end;
|
||||
|
||||
Reference in New Issue
Block a user