Closed lewissbaker closed 7 years ago
Started the process of removing use of task<T>
from tests in b78bc3ed7b0c2c13fb92483a6b34e31589e22286.
There are still the where_all_tests.cpp
and where_all_ready_tests.cpp
to go but I've been running into some crashes when updating these that I need to investigate.
Commit 722fe1b24a3d0cb5fbafa17ee167e2a024f59bf7 removes use of eager tasks from where_all_ready_tests.cpp
.
Only where_all_tests.cpp
to go.
Commit 421de76f189c1f38a621898eaec77dc3700b9c47 removes last of eager task usage from tests (except where testing eager tasks themselves).
Commit 64b0a049f9e07eef7082b1d4de31686975c3cdc8 removes the task<T>
and shared_task<T>
classes and updates the README.
All that remains now is renaming lazy_task
-> task
and shared_lazy_task
-> shared_task
.
Commit bf9eb2c58110a650cc4128bef03c8d9d87be62f7 has implemented the rename.
Closing.
Once we have a way to synchronously block waiting for a task in #27 and
when_all
in #10 there shouldn't be any need for the eagerly started task types any more and we can limit use to just the lazy task types (ie.lazy_task
andshared_lazy_task
)One of the big motivations for getting rid of eagerly-started tasks is that it is difficult to write exception-safe code with use of eagerly-started tasks that aren't immediately
co_await
ed.We don't want to leave dangling tasks/computation as this can lead to ignored/uncaught exceptions or unsynchronised access to shared resources.
For example, consider the case where we want to execute two tasks concurrently and wait for them both to finish before continuing, using their results:
To implement this in an exception-safe way we'd need to modify the function as follows:
Compared with
lazy_task
version which is both concise and exception-safe:With a
lazy_task
, the task is either beingco_await
ed by some other coroutine or it is not executing (it has either not yet started, or has completed executing) and so thelazy_task
is always safe to destruct and will free the coroutine frame it owns.A side-benefit of using
lazy_task
everywhere is that it can be implemented without the need forstd::atomic
operations to synchronise coroutine completion and awaiter. This can have some potential benefits for performance by avoiding use of atomic operations for basic sequential flow of execution.