3 ms·
Maybe the use of the word “cancel” can mislead some people, because the term means a much more controlled way of shutdown in other ecosystems. For example, you
by codeflo 5y ago
Maybe the use of the word “cancel” can mislead some people, because the term means a much more controlled way of shutdown in other ecosystems. For example, you can’t really stop Tasks in C# unless you explicitly pass around a CancellationToken and check it at strategic points — very similar to the one in Tokio: https://docs.rs/tokio-util/latest/tokio_util/sync/struct.CancellationToken.html https://docs.rs/tokio-util/latest/tokio_util/sync/struct.Can...
What dropping futures does in Rust is much more forceful, and possibly meant for a different usecase, or as a lower-level primitive.
- SigmundA 5y agoCancelling in Rust sound a lot like Thread.Abort() in .Net [1] just injects an exception arbitrarily into the thread and generally frowned upon due to potentially corrupt shared state and has been completely removed in later .Nets. Unless you treat threads like a full process (no shared state) then you need cooperative cancellation (CancellationToken) which generally works well its nice to have common agreed upon cancellation message most commonly used in async I/O calls like a long running a DB query and wanting to cancel it if the client disconnects because they navigated away. If you have uncooperative code that may say go into an infinite loop then you need to somehow preempt it if it runs on too long so then you have Thread.Abort or really Process.Kill which is the only safe way to do this in .Net (run it in another process). [1] https://docs.microsoft.com/en-us/dotnet/api/system.threading.thread.abort?view=net-6.0 https://docs.microsoft.com/en-us/dotnet/api/system.threading...
- notriddle 5y agoIt only happens at `await` points. This means you don’t need to worry about it leaving an invalid BTreeMap or anything, only code that actually does async work needs to worry about being canceled.
- SigmundA 5y agoHmm the article says: In effect, if you look at things from the “inside view” of the async fn, cancellation looks like the await call panicking – it unwinds the stack, running the destructors for all values. The analogy, of course, only goes so far: you can’t, for example, “catch” the unwinding from a cancellation. Also, panics arise from code that the thread executed, but cancellations are injected from the outside when the async fn’s result is no longer needed It also references Javas deprecated Thread.stop which looks very similar to .Nets Thread.Abort
- maxwell86 5y ago> cancellation looks like *the await call* panicking Emphasis mine. In Rust, "cancellation" happens at well defined "await points".
- SigmundA 5y agoThanks for clearing that up, I missed that detail. So it seems similar to Tasks in .Net that check the cancellation token before starting and will throw on await. However in .Net you can check IsCancellationRequested in your code once the Task is running to decide how to cancel or just ThrowIfCancellationRequested() . Then you try catch your awaits to handle cancellation (or not). In Thread.Abort the .Net runtime is just injecting a call to throw into the instructions at potentially any point in the threads code which is obviously problematic although throwing on any await can still cause problem if you're not expecting it. There is no try catching involved because you really can't catch ThreadAbortException instead you are just waiting for the thread to stop with Thread.Join or what ever.
- codeflo 5y agoI don’t think it’s similar at all, that was my point. The .NET runtime itself will never check a CancellationToken for you, but an API you pass it to might, of course (and many standard APIs take one as a parameter). And even then, the result is an exception, which you can catch and keep going. That’s not at all what happens when the Future is dropped in Rust: Yes, it only happens at .await, but when it does, execution is simply stopped dead, no chance to continue.
- SigmundA 5y agoUsing the await keyword in C# a TaskCanceledException will be thrown automatically regardless if you check it or not, it just won't stop your code once running the task starts, it checks before start and at the end to set the task and sets to a canceled state which leads to an exception. Rust seems to just have exceptions you can't catch (Panics) they are like ThreadAbortExceptions in .Net. That is if task threw ThreadAbortExceptions instead of TaskCanceledException and you called await with an already cancelled token you would get similar behavior it seems.
- codeflo 5y agoI think that depends a bit on what you intended to do after the await. I’m certain there are uses of an async mutex (several libraries have one) where there’s indeed a broken invariant.
- amalcon 5y agoJava has thread.stop(), which does a similar thing and is deprecated for similar reasons. https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#stop-- https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.h... I remember trying to use it once, in my more reckless days and despite the warnings, thinking it's all fine if I just wrap all intermediate states in try/finally. It turns out that sometimes this will cause a throw in the finally clean-up, so you need to use a try/catch+rethrow and repeat yourself a bit. It's still not quite right, though, because you can still throw in the catch...