diff --git a/Src/Myc.Core.Tasks.pas b/Src/Myc.Core.Tasks.pas index 1dbcd69..ccb7395 100644 --- a/Src/Myc.Core.Tasks.pas +++ b/Src/Myc.Core.Tasks.pas @@ -41,13 +41,6 @@ type // will be re-raised in the calling (main) thread. procedure Teardown; - // 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(State: IMycState); - // Gets the number of worker threads. property ThreadCount: Integer read GetThreadCount; end; @@ -89,6 +82,7 @@ type function InMainThread: Boolean; function InWorkerThread: Boolean; + // Initialize global TaskManager class procedure AquireTaskManager; class procedure ReleaseTaskManager; end; diff --git a/Src/Myc.Futures.pas b/Src/Myc.Futures.pas index 4bf4c7f..0f3a66f 100644 --- a/Src/Myc.Futures.pas +++ b/Src/Myc.Futures.pas @@ -22,14 +22,26 @@ type Future = record strict private FFuture: IMycFuture; + function GetDone: IMycState; inline; + function GetResult: T; inline; + class constructor CreateClass; class destructor DestroyClass; - constructor Create(const AFuture: IMycFuture); - public - class function Construct(const Proc: TFunc): Future; overload; static; - class function Construct(const Gate: IMycState; const Proc: TFunc): Future; overload; static; - function Chain(const Proc: TFunc): Future; + public + constructor Create(const AFuture: IMycFuture); + class operator Implicit(const A: IMycFuture): Future; overload; + class operator Implicit(const A: Future): IMycFuture; overload; + + class function Construct(const Proc: TFunc): IMycFuture; overload; static; + class function Construct(const Gate: IMycState; const Proc: TFunc): IMycFuture; overload; static; + + function Chain(const Proc: TFunc): IMycFuture; + + function WaitFor: T; + + property Done: IMycState read GetDone; + property Result: T read GetResult; end; implementation @@ -52,7 +64,7 @@ begin TMycTaskFactory.ReleaseTaskManager; end; -function Future.Chain(const Proc: TFunc): Future; +function Future.Chain(const Proc: TFunc): IMycFuture; begin var Cap := FFuture; @@ -63,14 +75,40 @@ begin end ); end; -class function Future.Construct(const Proc: TFunc): Future; +class function Future.Construct(const Proc: TFunc): IMycFuture; begin - Result.Create( TMycInitStateFuncFuture.Create( TaskManager, nil, Proc ) ); + Result := TMycInitStateFuncFuture.Create( TaskManager, nil, Proc ); end; -class function Future.Construct(const Gate: IMycState; const Proc: TFunc): Future; +class function Future.Construct(const Gate: IMycState; const Proc: TFunc): IMycFuture; begin - Result.Create( TMycInitStateFuncFuture.Create( TaskManager, Gate, Proc ) ); + Result := TMycInitStateFuncFuture.Create( TaskManager, Gate, Proc ); +end; + +function Future.GetDone: IMycState; +begin + Result := FFuture.Done; +end; + +function Future.GetResult: T; +begin + Result := FFuture.Result; +end; + +function Future.WaitFor: T; +begin + TaskManager.WaitFor( FFuture.Done ); + Result := FFuture.Result; +end; + +class operator Future.Implicit(const A: IMycFuture): Future; +begin + Result.Create( A ); +end; + +class operator Future.Implicit(const A: Future): IMycFuture; +begin + Result := A.FFuture; end; end. diff --git a/Src/Myc.TaskManager.pas b/Src/Myc.TaskManager.pas index c46ee00..1b59796 100644 --- a/Src/Myc.TaskManager.pas +++ b/Src/Myc.TaskManager.pas @@ -9,6 +9,13 @@ uses type IMycTaskManager = interface function CreateTask( const Gate: IMycState; const Proc: TProc ): TMycSubscription; + + // 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(State: IMycState); end; var diff --git a/Test/MycTests.dpr b/Test/MycTests.dpr index c0102d3..83bd83b 100644 --- a/Test/MycTests.dpr +++ b/Test/MycTests.dpr @@ -24,10 +24,11 @@ uses TestTasks in 'TestTasks.pas', TestSignals_Dirty in 'TestSignals_Dirty.pas', Myc.Futures in '..\Src\Myc.Futures.pas', - TestFutures in 'TestFutures.pas', + TestCoreFutures in 'TestCoreFutures.pas', Myc.TaskManager in '..\Src\Myc.TaskManager.pas', Myc.Core.Futures in '..\Src\Myc.Core.Futures.pas', - Myc.Core.Signals in '..\Src\Myc.Core.Signals.pas'; + Myc.Core.Signals in '..\Src\Myc.Core.Signals.pas', + TestFutures in 'TestFutures.pas'; { keep comment here to protect the following conditional from being removed by the IDE when adding a unit } {$IFNDEF TESTINSIGHT} diff --git a/Test/MycTests.dproj b/Test/MycTests.dproj index e473c6c..029bcac 100644 --- a/Test/MycTests.dproj +++ b/Test/MycTests.dproj @@ -123,10 +123,11 @@ $(PostBuildEvent)]]> - + + Base diff --git a/Test/TestFutures.pas b/Test/TestCoreFutures.pas similarity index 97% rename from Test/TestFutures.pas rename to Test/TestCoreFutures.pas index 642f22b..68252bc 100644 --- a/Test/TestFutures.pas +++ b/Test/TestCoreFutures.pas @@ -1,4 +1,4 @@ -unit TestFutures; +unit TestCoreFutures; interface