7 ms·
In case anyone else is interested in reading it, the relevant RFC is here: https://github.com/rust-lang/rfcs/blob/master/text/1504-int128.md https://github.com/
by andars 10y ago
In case anyone else is interested in reading it, the relevant RFC is here: https://github.com/rust-lang/rfcs/blob/master/text/1504-int128.md https://github.com/rust-lang/rfcs/blob/master/text/1504-int1...
- drfuchs 10y agoThe RFC doesn't seem to mention anything about the atomicity (or lack thereof) of loads and stores of variables of the 128-bit types. From the discussion, it seems that on a number of current architectures, they're not going to be atomic. Does this cause any problems in the Rust view of the world? Will there be unanticipated issues for developers who have been getting along just fine so far unknowingly assuming that all operations are atomic, which they have been just by virtue of how the hardware works?
- steveklabnik 10y agoRust has separate atomic types for doing atomic operations, so currently, none of them are. So, if you wanted an atomic type, you'd find it here: https://doc.rust-lang.org/stable/std/sync/atomic/index.html https://doc.rust-lang.org/stable/std/sync/atomic/index.html In other words, no, it shouldn't be a problem, at least in my understanding.
- drfuchs 10y agoRight, but the point is that to date, being careless about asking for an atomic type explicitly would not lead to buggy behavior. But now it will, so some folks are going to be stumped when they use their old habits and get flakey results. Not that there's anything to be done, other than warning folks that they can't just widen their integer types and expect it to work without checking for this case.
- steveklabnik 10y agoIn Rust, you don't get buggy behavior in this kind of case: your program fails to compile.
- Tuna-Fish 10y agoThe situation where the atomicity of integer operations matter is when there are multiple references to a single memory location, at least one of which is mutable. The entire basis of the memory protection model of Rust is that it makes the above impossible in safe code. If you attempt to create such a situation, the compiler will fail to compile your code. Every single integer operation could stop being atomic and not a single line of safe rust would break.
- cesarb 10y ago> Right, but the point is that to date, being careless about asking for an atomic type explicitly would not lead to buggy behavior. That's already the case: simply reading a 64-bit integer in a 32-bit processor is not atomic, and that's already possible today. But that's not a problem in Rust. How would you access the same 128-bit integer from more than one thread? - You pass the thread a copy of the value: the thread's copy can't be accessed by any other thread, so whether or not it's atomic doesn't matter. - You pass the thread a mutable reference (&mut) to the value: one of Rust's rules is that there can be only one &mut to a memory location, and while that &mut exists, nothing else can read or modify the value. Therefore it's the same case: only one thread can access the value, so whether or not it's atomic doesn't matter. - You pass the thread a non-mutable reference (&) to the value: another of Rust's rules is that while any non-mutable reference exists, nothing can modify the value, so the reads not being atomic don't matter. - You wrap the value in something like a Mutex: the Mutex has a lock which prevents concurrent accesses in the middle of a write. - You use an Atomic version of the 128-bit integer: this one doesn't exist, so can't be used. The main reason for all the interest in Rust is that the compiler protects you from many kinds of mistakes. Accessing the same variable from more than one thread, without using a lock or an atomic, is one of the things the compiler protects you from.
- dbaupp 10y agoOne of Rust's strongest features is its ability to outlaw data races. In this case, the 128-bit types only provide mutations that take &mut self, that is, a unique unaliased pointer, meaning there's no way to concurrently mutate and hence they are automatically atomic, in a sense.
- deleted 10y ago[deleted]
- chrisseaton 10y agoDoes Rust run a memory barrier when ownership is transferred? How does it ensure that the previous owner has finished all its writes when a new owner take over?
- stjepang 10y agoTo transfer ownership, you would wrap the object in Mutex<T>, send it via Sender<T>, use some other synchronization primitive, or simply pass it over at the moment the thread is spawned. It's up to the synchronization primitives to ensure memory barriers are executed, not the language. So e.g. a Mutex<T> would execute a memory barrier when locking and unlocking. Rust then allows you to pass ownership in a trusted manner only, i.e. through those primitives. Of course, you can also create an unsafe block and say: "Rust, trust me, I know what I'm doing, don't bother me, and these are the invariants I want you to enforce in safe code..." Mutexes are implemented this way.
- dardie 10y agoIt's built into the type system and checked statically at compile time. In rust, there can only be one 'owner' of a stored value. Ownership can be transferred, borrowed by multiple readers, or borrowed by a single writer. This ensures (at compile time) that there at any given time there is only ever one single writer OR multiple readers. Rust programs are guaranteed to be free of race conditions at compile-time. The above covers the vast majority of situations, but for cases where this is too restrictive their are other language constructs such as reference-counted types.
- the_duke 10y agoI what drfuchs might be getting at is that 128bit integers would need two registers on a 64bit architecture. Or four on a 32 bit one. LLVM supports arbitrary length integer types, regardless of the platform. Rust already has u64 and i64 on 32bit architectures. But even if something fits in one register, a variable isn't thread safe anyway. Rust DOES NOT allow a mutable reference to exist simultaneously with non-mutable ones. For thread safety, you always need special types, which Rust provides: https://doc.rust-lang.org/std/sync/atomic/ https://doc.rust-lang.org/std/sync/atomic/ https://doc.rust-lang.org/std/sync/struct.Arc.html https://doc.rust-lang.org/std/sync/struct.Arc.html
- drfuchs 10y agoThanks, but to be even more explicit, I'm thinking of a lower level than thread safety and the nice atomic references Rust provides in "safe" code: Consider a systems-y program that handles signals, or even hardware interrupts, or mmaps a chunk of shared memory. Any Read of a 32-bit variable will produce a value that was Written previously, no matter what; the hardware guarantees it. But a Read of a 128-bit variable may result in a value that has the high 64 bits from one earlier Write, and the low 64 bits from a more recent Write that was interrupted (or vice-versa). That's different than what many folks have ever experienced, messes up some algorithms, and is sure confusing the first time you see it. True, this won't come up in a run-of-the-mill program, but if Rust is going to supplant C for OS work, or DataBase implementations, this is an issue to be aware of. Succinctly: If you're in unsafe code, using 128-bit integers, you may experience behavior you've never seen before.
- snovv_crash 10y agoThat kind of non-safe memory sharing doesn't exist in Rust, unless you explicitly mark code as 'unsafe'. If you want to write a variable, nobody else is allowed to read it until you are finished, and this is enforced at compile time via the language design. The same is true for all data structures.
- Manishearth 10y agoAll the Rust OSes written right now use pretty tightly scoped unsafe code. The OS isn't just unsafe-blocks-everywhere. The compiler would force you to use an atomic. Once you realize no AtomicUint128 atomic exists, you may try to explicitly use unsafe to make things work, but even then that requires a lot more explicitness than just an unsafe block. You will realize your mistake some point here. Unsafe in Rust doesn't just turn off all the checks. It gives you the power to circumvent the checks, but these circumventions are still individually explicit. Anyway, u128 doesn't worsen this situation. You could already make thread safety mistakes with wider value types if you really really wanted to, just like u128.