-
Notifications
You must be signed in to change notification settings - Fork 18k
proposal: context: reconsider semantics for AfterFunc stop function #60156
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I would phrase the proposed alternative semantic as something like:
That is, the function may not have been invoked yet, but if stop returns false it definitely will be. I like these semantics better than the |
I agree that's somewhat unfortunate, but the |
The discussion in #57928 around stop focused on whether stop blocks until f is done, not on what happens when stop is called multiple times. We didn't directly discuss what the second call to stop should return. If you think that f is going to do something important that needs to happen exactly once, then this pattern
is well supported by stop returning true from only one of its concurrent calls. The time.Timer API is confusing because if you didn't get f in time you need to do cleanup (<-t.C), but only once, and the result doesn't actually help with that. But that specific cleanup won't happen with AfterFunc. (That is, the confusing part about Timer is when you're using the channel form, not the AfterFunc form.) Is there a use case for context.AfterFunc where these stop semantics are problematic? Both of the links in the top message here are about time.Timer.C. |
If you think that f is going to do something important that needs to happen exactly once, then I'd suggest that this pattern:
is probably sufficient and fairly natural. On the other hand, finding out whether the function has run (or is about to run) is a little more awkward with the original semantics:
The issue is that the function might be about to be run and we can't tell that from the result of stop. I guess that's possible to work around by wrapping
So both semantics are implementable in terms of the other. I happen to think that the behaviour I suggested is a bit more intuitive and easily explained, as it makes the return from |
This is subtly but importantly not correct: If I think that the common use for the return value of I'm not certain under what circumstances we might call |
This proposal has been added to the active column of the proposals project |
Based on the discussion above, it sounds like we should leave it matching AfterFunc. |
Based on the discussion above, this proposal seems like a likely decline. |
No change in consensus, so declined. |
I raised this point in #57928.
I'm not entirely sure whether the semantics of the
stop
return fromcontext.AfterFunc
are correct. The argument for it being this way is by reference toTimer.Stop
but I'm not convinced thatTimer.Stop
is good precedent, because that API is notoriously error-prone and hard to use.An alternative semantic could be:
That makes it feasible to call
stop
multiple times concurrently and have consistent results between them, and it seems to me like a simpler invariant to explain.I'm wondering what the use case is for knowing whether this is the
stop
call that prevented the function running.The text was updated successfully, but these errors were encountered: