You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
One problem I ran into is "stack use after scope" when doing this. This is because derived class's stack memory may have been freed before the base context is executed. That means that the derived classes will need to call cancel() themselves in order to cancel their operations.
I've been also thinking about when this would actually be important. For example, in what scenarios can a context be destroyed and it still have an operation on its stack.
First, to even have an operation on the context stack, a future must exist somewhere that is bound to the context. If that future is destroyed, then it's operation and all sub operations are destroyed as well, leaving context empty with no need to call cancel itself.
One could stack their operations, but once that's done, the memory is leaked and your stuck anyways. This would be erroneous behaviour.
Another idea is if a future is moved from its scope to one that will extend its lifetime past the context, like moving the future to a global variable. If that happens then the lifetime of the future will outlive the context and the context will need to invoke cancel.
Since futures can only be created with an existing context, they must have lifetimes shorter than the context it's associated with.
So my thoughts are:
Could a future be moved to dynamics memory extending its life to an unknown time?
Could a future be moved to a global variable or to a member of a class?
Could a future be placed into an optional<future<T>> that's above the creation of a context?
One idea is to make futures immovable to prevent 1 and 2. But I don't think we can prevent a future from being constructed / assigned into some other container with greater lifetime than its context, such as vector or optional.
So due to the 3rd thought above, I think we just need to do some checking to ensure we don't call destroy on things. This would require derived classes to call cancel(). And maybe we need a terminate clause if a context is destroyed but it's stack memory is empty.
I went with adding a type erased function to each promise to allow it cancel any typed future. This enables us to easily set each future to the cancelled state as we propagate from the bottom active coroutine up the chain.
Activity
kammce commentedon Jan 14, 2026
Changing this to a bug because it is one and its problematic. Currently, calling cancel in the destructor causes a segfault.
kammce commentedon Jan 16, 2026
One problem I ran into is "stack use after scope" when doing this. This is because derived class's stack memory may have been freed before the base context is executed. That means that the derived classes will need to call
cancel()themselves in order to cancel their operations.I've been also thinking about when this would actually be important. For example, in what scenarios can a context be destroyed and it still have an operation on its stack.
First, to even have an operation on the context stack, a future must exist somewhere that is bound to the context. If that future is destroyed, then it's operation and all sub operations are destroyed as well, leaving context empty with no need to call cancel itself.
One could stack their operations, but once that's done, the memory is leaked and your stuck anyways. This would be erroneous behaviour.
Another idea is if a future is moved from its scope to one that will extend its lifetime past the context, like moving the future to a global variable. If that happens then the lifetime of the future will outlive the context and the context will need to invoke cancel.
Since futures can only be created with an existing context, they must have lifetimes shorter than the context it's associated with.
So my thoughts are:
optional<future<T>>that's above the creation of a context?One idea is to make futures immovable to prevent 1 and 2. But I don't think we can prevent a future from being constructed / assigned into some other container with greater lifetime than its context, such as vector or optional.
So due to the 3rd thought above, I think we just need to do some checking to ensure we don't call destroy on things. This would require derived classes to call cancel(). And maybe we need a terminate clause if a context is destroyed but it's stack memory is empty.
kammce commentedon Jan 17, 2026
Resolved in #56
I went with adding a type erased function to each promise to allow it cancel any typed future. This enables us to easily set each future to the cancelled state as we propagate from the bottom active coroutine up the chain.