| Atomic ops only address a small part of the problem.* Sure, your internal queue pointers will be sane, and two-stage register settings won't be interrupted. But locks are very fine-grained, and aren't going to help you keep co-ordinated in-the-large. In fact, you could argue that each mutex is a warning about muddled coordination. "Who's going to be changing this queue?" "Everybody!" "Better put a lock around it." Yes, it's all trade-offs. You aren't going to avoid all shared responsibility, and will always need micro-coordination. But safe Rust forces you to assign ownership to every structure, at every scale. Some similar effects to opaque data structures, or actors. But unlike those techniques, it allows you to dynamically transfer responsibility. The most obvious issue is use-after-"free", use-before-"allocate". "Free" and "allocate" don't just refer to malloc--it's any situation where you pinky-swear you aren't going to be touching something. But more problematic is this kind of code is easy, even natural, to write in C: - Task A is waiting for a state changes on resources Q1 and Q2. When it sees a particular set, it will modify resource Q3's state. - Task B is firing off events to Q1 and handling error responses. It might need to stop Q1. - Since Q1 is no longer changing state, what happens to Q3? Who's responsible for keeping stuff straight? What's "stuff"? Do we need to worry about Q2? Rust is going to very strongly push you to explicitly designate what owns and is responsible for Q1, Q2, Q3, at all times. "B's got Q1, so A can't even look at it. I'm @#!* going to have to make A tell B what it wants and let B handle it." That was painful, but a good thing. * Note to self: Write a blog post titled "Atomics won't save you now!" Start a band named "Useless Atomics". |