Implement part of the std::execution paper https://wg21.link/P2300
syncWait(taskManager.schedule() | then([]{return 5;}));
The user has only to deal with senders: sender-factories(taskManager), sender-adoptor(then) and sender-consumer(syncWait). Those can be chained together to build a execution-graph.
The type of the adapted sender will be:
Then::Send<TaskManager::Send>
A sender-consumer will connect the adapted sender to its receiver and get an operation state which holds all information about the task:
Then::State<TaskManager::State<Then::Recv<SyncWait::Recv>>>
The sender-consumer then calls Then::State<...>::Start() which calls TaskManager::State<...>::Start(). TaskManager::State<...>::Start() attaches "work" to the queue. If the "work" get scheduled one thread will call Then::Recv<...>::SetValue(). Then::Recv<...> will execute the actual function. If it succeeds SyncWait::Recv::SetValue() is called, if an exception is thrown SyncWait::Recv::SetError() is called. SyncWait will return the value or rethrow the exception.
changes from P2300:
- Only two sender adoptor are implemented: then, whenAll.
- There are two sender consumer: syncWait, asFuture. asFuture is not part of P2300 but i think it is usefull.
- In this implementation only one variable is passed through the execution-chain.
- whenAll passes a tuple were each sender have there element. P2300 concats all sender-results together and don't use tuple.
- I didnt implement tag_invoke
WIP
- implement cancelation
- make TaskManager a scheduler
- some optimisation copy -> move