3 ms·
While I think the problem highlighted in the article is a longstanding problem for Rust[1], I don't think the example, or finalizers was the problem with Future
by nemothekid 11mo ago
While I think the problem highlighted in the article is a longstanding problem for Rust[1], I don't think the example, or finalizers was the problem with Futurelock as described by Oxide.
I'm not sure you can write a simple example in Python, because Rust's future's architecture and Python's is different. `futurelock` is an issue of cancellation safety which is a stranger concept (related to finalizers, but not in the way OP has described).
Personally, I think `tokio::select!` is dangerous and I don't use it my code - it's very easy to deadlock yourself or create weird performance issues. I think the interface is too close to Go and if you don't understand what is going on, you can create deadlocks. That said, even if you avoid `tokio::select!`, I think cancellation safety is one of those dragons that exist in async rust.
[1] https://without.boats/blog/poll-drop/ https://without.boats/blog/poll-drop/
- nemothekid 11mo agoThe `futurelock` is probably closer to something like: import threading mutex = threading.Lock() def gen_1(): yield 1 print("acquiring") mutex.acquire(); print("acquired") yield 2 print("releasing") mutex.release() yield 3 def gen_2(): yield "a" def do_something_else(): print("im gonna do something else") mutex.acquire() print("acquired") mutex.release() print("done") a = gen_1(); b = gen_2(); zipped_data = zip(a, b) for num, letter in zipped_data: print("output", num, letter) do_something_else() print("done") Here you can see that `gen_1` "holds" the lock, even though we are done with it, and `gen_1` won't release it until `next` is called again. The problem is before `do_something_else` is called, either `a` must be destroyed or someone has to call `next` on it. However from just reading the code, the fact that this exists can be difficult to see.