diff --git a/tutorial/CoreTutorial/Async.cpp b/tutorial/CoreTutorial/Async.cpp new file mode 100644 index 000000000..2b212dd4d --- /dev/null +++ b/tutorial/CoreTutorial/Async.cpp @@ -0,0 +1,48 @@ +#include "Tutorial.h" + +void AsyncTutorial() +{ + /// .`AsyncWork` + + /// `AsyncWork` is `CoWork` based tool that resembles std::future. `AsyncWork` instances + /// are created using `Async` function and represent a work that can be done in parallel + /// with current thread. `AsyncWork` supports returning values. A call to `AsyncWork::Get` + /// makes sure that a work routine was finished and returns the return value (if any): + + auto a = Async([](int n) -> double { + double f = 1; + for(int i = 2; i <= n; i++) + f *= i; + return f; + }, 100); + + DUMP(a.Get()); + + /// Exceptions thrown in Async work are propagated upon call to `Get`: + + auto b = Async([] { throw "error"; }); + + try { + b.Get(); + } + catch(...) { + LOG("Exception has been caught"); + } + + /// `AsyncWork` instances can be canceled (and are canceled in destructor if Get is not + /// called on them): + + { + auto c = Async([] { + for(;;) + if(CoWork::IsCanceled()) { + LOG("Work was canceled"); + break; + } + }); + Sleep(100); // give it chance to start + // c destructor cancels the work (can be explicitly canceled by Cancel method too) + } + + /// +} diff --git a/tutorial/CoreTutorial/CoWork.cpp b/tutorial/CoreTutorial/CoWork.cpp index 222251eac..1a86d3c42 100644 --- a/tutorial/CoreTutorial/CoWork.cpp +++ b/tutorial/CoreTutorial/CoWork.cpp @@ -35,7 +35,7 @@ void CoWorkTutorial() DUMP(w); /// Adding words to `w` requires `Mutex`. Alternative to this 'result gathering' `Mutex` is - /// CoWork::FinLock. The idea behind this is that CoWork requires an internal `Mutex` to + /// `CoWork::FinLock`. The idea behind this is that CoWork requires an internal `Mutex` to /// serialize access to common data, so why `FinLock` locks this internal mutex a bit /// earlier, saving CPU cycles required to lock and unlock dedicated mutex. From API /// contract perspective, you can consider `FinLock` to serialize code till the end of @@ -55,7 +55,33 @@ void CoWorkTutorial() DUMP(w); - /// Of course, the code performed after FinLock should not take long, otherwise there is - /// negative impact on all CoWork instances. In fact, from this perspective, above code is - /// probably past this threshold... + /// Of course, the code performed after `FinLock` should not take long, otherwise there is + /// negative impact on all `CoWork` instances. In fact, from this perspective, above code is + /// probably past the threshold... + + /// When exception is thrown in `CoWork`, it is propagated to the thread that calls `Finish`. + /// As `CoWork` destructor calls `Finish` too, it is possible that it will be thrown by + /// destructor, which is not exactly recommended thing to do in C++, but is well defined + /// and really the best option here: + + try { + CoWork co; + co & [] { throw Exc(); }; + } + catch(Exc) { + LOG("Caught exception"); + } + + /// Sometimes there is a need for cancellation of the whole `CoWork`. `Cancel` method + /// cancels all scheduled jobs that have not been yet executed and sets `CoWork` to + /// canceled state, which can be checked in job routine using `CoWork::IsCanceled`: + + co & [] { + for(;;) + if(CoWork::IsCanceled()) + return; + }; + co.Cancel(); + + /// } diff --git a/tutorial/CoreTutorial/CoreTutorial.upp b/tutorial/CoreTutorial/CoreTutorial.upp index e2214db92..71cff7470 100644 --- a/tutorial/CoreTutorial/CoreTutorial.upp +++ b/tutorial/CoreTutorial/CoreTutorial.upp @@ -44,6 +44,7 @@ file ConditionVariable.cpp, test.txt, CoWork.cpp, + Async.cpp, CoPartition.cpp, Parallel.cpp, tutorial2.cpp, diff --git a/tutorial/CoreTutorial/tutorial2.cpp b/tutorial/CoreTutorial/tutorial2.cpp index 6cf9bf738..21e522fdb 100644 --- a/tutorial/CoreTutorial/tutorial2.cpp +++ b/tutorial/CoreTutorial/tutorial2.cpp @@ -49,6 +49,7 @@ GUI_APP_MAIN DO(MutexTutorial); DO(ConditionVariableTutorial); DO(CoWorkTutorial); + DO(AsyncTutorial); DO(CoPartitionTutorial); DO(CoAlgoTutorial);