-
Notifications
You must be signed in to change notification settings - Fork 95
4. Quick reference guide
Head-to-head comparison of features.
Feature | V1 | V2 | Notes |
---|---|---|---|
Decouples returning value with coroutine termination | Yes | No | |
Computed value | Set via promise or context
|
Returned directly | |
Flexibility | Higher | Lower | |
Supports buffered futures | Yes | No | In V2 api similar behavior has be be created out-of-band |
Convert a regular function to a coroutine | Harder | Easier | Async IO tasks require no modification in V2 api! |
Support exceptions | Yes | Yes | |
Can nest coroutines or IO tasks | Yes | Yes |
The following table shows the main coroutine and async IO task V1 signatures that are required and the context in which they are executed. These functions can represent any callable object such as lambdas or regular functions.
Coroutine task | AsyncIo task |
---|---|
int (CoroContextPtr<T>, Args&&...) |
int (ThreadPromisePtr<T>, Args&&...) |
// Posting a V1 coroutine
ThreadFuturePtr<T> tctx = dispatcher.postAsyncIo([](CoroContextPtr<T> ctx)->int{
//do stuff...
ctx->set(T{}); //return future. main task awakes here
//do stuff...
return 0;
});
// Compact version
ThreadFuturePtr<T> tctx = dispatcher.postAsyncIo([](CoroContextPtr<T> ctx)->int{
//do stuff...
return ctx->set(T{}); //main task awakes here
});
// Posting a V1 async IO
ThreadFuturePtr<T> tctx = dispatcher.postAsyncIo([](ThreadPromisePtr<T> promise)->int{
//do stuff...
promise->set(T{}); //return future. main task awakes here
//do stuff...
return 0;
});
// Compact version
ThreadFuturePtr<T> tctx = dispatcher.postAsyncIo([](ThreadPromisePtr<T> promise)->int{
//do stuff...
return promise->set(T{}); //return future. main task awakes here
});
The following table shows the main coroutine and async IO task signatures that are required if using the simpler V2 API. Note that VoidContextPtr
is a class similar to CoroContextPtr<T>
except that it does not support setting any values since values are returned directly on the return
line. Also it is not templated on any type.
Coroutine task | AsyncIo task |
---|---|
T (VoidContextPtr, Args&&...) |
T (Args&&...) |
// Posting a V2 coroutine
ThreadContextPtr<T> tctx = dispatcher.post2([](VoidContextPtr ctx)->T {
//do stuff...
return T{}; //return future. main task awakes here
});
// Posting a V2 async IO
ThreadFuturePtr<T> tctx = dispatcher.postAsyncIo2([]()->T {
//do stuff...
return T{}; //return future. main task awakes here
});
Note: V2 api dispatcher functions have the same name as V1 counterparts but with a 2
appended (post2()
, postAyncIo2()
etc.)
Main
below refers simply to your application's main thread or any other thread outside of the quantum framework.
Method | Instance | Location | Return Type |
---|---|---|---|
post()/post2() | Dispatcher |
main | ThreadContextPtr<T> |
post()/post2() |
CoroContextPtr<T> /VoidContextPtr
|
coroutine | CoroContextPtr<T> |
postAsyncIo()/postAsyncIo2() | Dispatcher |
main | ThreadFuturePtr<T> |
postAsyncIo()/postAsyncIo2() |
CoroContextPtr<T> /VoidContextPtr
|
coroutine | CoroFuturePtr<T> |
postFirst()/postFirst2() | Dispatcher |
main | ThreadContextPtr<T> |
postFirst()/postFirst2() |
CoroContextPtr<T> /VoidContextPtr
|
coroutine | CoroContextPtr<T> |
then()/then2() | ThreadContextPtr<T> |
main | ThreadContextPtr<T> |
then()/then2() |
CoroContextPtr<T> /VoidContextPtr
|
coroutine | CoroContextPtr<T> |
onError()/onError2() | ThreadContextPtr<T> |
main | ThreadContextPtr<T> |
onError()/onError2() |
CoroContextPtr<T> /VoidContextPtr
|
coroutine | CoroContextPtr<T> |
finally()/finally2() | ThreadContextPtr<T> |
main | ThreadContextPtr<T> |
finally()/finally2() |
CoroContextPtr<T> /VoidContextPtr
|
coroutine | CoroContextPtr<T> |
end() | ThreadContextPtr<T> |
main | ThreadContextPtr<T> |
end() |
CoroContextPtr<T> /VoidContextPtr
|
coroutine | CoroContextPtr<T> |
Note that objects in quantum are named using the location in which they are supposed to be used for disambiguation. As such CoroContextPtr<T>
can only appear in a coroutine, and ThreadPromise<T>
can only appear in a regular thread (async IO task).
It is also perfectly possible to combine V1 and V2 apis:
auto ctx = dispatcher.postFirst(...)->then2(...)->then(...)->finally2(...)->end();
The following functions block or yield implicitly with the exception of yield()
which yields explicitly. Note that ICoroSync
is a base class of CoroContext<T>
and as such the derived class can be passed directly into the function.
Method | Instance | Location | Action | Requires CoroSyncPtr as argument |
---|---|---|---|---|
yield() |
CoroContextPtr<T> /VoidContextPtr
|
coroutine | yields | yes |
getXXX() | ThreadContextPtr<T> |
main | blocks | no |
getXXX() |
CoroContextPtr<T> /VoidContextPtr
|
coroutine | yields | yes |
set() | ThreadPromisePtr<T> |
IO thread | blocks(1) | no |
set() |
CoroContextPtr<T> /VoidContextPtr
|
coroutine | yields(1) | no |
push() | ThreadPromisePtr<T> |
IO thread | blocks(1)(2) | no |
push() |
CoroContextPtr<T> /VoidContextPtr
|
coroutine | blocks(1)(2) | no |
pull() | ThreadContextPtr<T> |
main | blocks(2) | no |
pull() |
CoroContextPtr<T> /VoidContextPtr
|
coroutine | yields(2) | yes |
waitXXX() | ThreadContextPtr<T> |
main | blocks | no |
waitXXX() |
CoroContextPtr<T> /VoidContextPtr
|
coroutine | yields | yes |
lock() | Mutex |
main | blocks | no |
lock() | Mutex |
coroutine | yields | yes |
waitXXX() | ConditionVariable |
main | blocks | no |
waitXXX() | ConditionVariable |
coroutine | yields | yes |
(1) May block for a very small period of time if there is contention on the shared promise/future state. (2) Only applicable to buffered futures.
Note that auto
can drastically simplify your code and reduce typing:
// Posting a V1 async IO
ThreadFuturePtr<T> tctx = dispatcher.postAsyncIo([](ThreadPromisePtr<T> promise)->int{
return promise->set(42);
});
Now becomes...
// Posting a V1 async IO
auto tctx = dispatcher.postAsyncIo([](auto promise)->int{
return promise->set(42);
});