Open jbruechert opened 2 years ago
Hi Jonah,
adding the context to .then() makes sense, but I think it's not as simple as it sounds:
QCoro::Task<int> task = gimmeTask();
const auto result = co_await task.then(someObject, [someObject](int result) {
return someObject->magicalNumber() + result;
});
If someObject
is destroyed while the task
is still running, you will skip calling the .then() continuation, but now you need to figure out what to do with the co_await
, because you don't have a result for it. Should it simply not be resumed, ever? This might make the application stuck...
One option would be to join this with the #107 and allow context object only on CancellableTask<T>::then()
, where the result of the chain would be a cancelled Result<U>
, if the context object was destroyed.
That seems like a good idea!
In some cases, one might want to update an object (for example a model), when a coroutine finished. This can be done by either using a lambda that captures
this
as a coroutine, or by adding a coroutine member function. However there is no guarantee that once the coroutine finishes, the object still exists, so this can lead to crashes.It is pretty much the same issue as the 3-arg connect in Qt: https://github.com/KDE/clazy/blob/master/docs/checks/README-connect-3arg-lambda.md
Is this already a solved problem in some way that I have missed?
If not, I propose adding an overload of
QCoro::Task<T>::then
that takes aQObject
pointer as an additional argument, so that it can connect toQObject::destroyed
of the context object, and not invoke the continuation if the signal has been emitted in the meantime.I currently can't find a good way to fix this when using the
co_await
keyword, but as this mostly concerns the issue of interaction between coroutine code and sync code, support in .then is probably enough.If needed, there could be something like
to inject the context even though using
co_await
.I already have code for some of the proposed things here, so I can work on implementing it if needed.