8 ms·
deleted
by jganetsk 6y ago
deleted
- Arnavion 6y ago>The comment for the take method claims that put and take can be called be concurrently with each other. But both call get() on an UnsafeCell. They can be called concurrently with each other, but the call to `UnsafeCell::get()` is guarded by an acquire-release latch for precisely that reason. This is already explained in the article. >I'm scratching my head on the syntax. There is no read() method on MaybeUninit. Also, the type passed to the write() method is wrong. I need to clone this and see if I can compile this. read() and write() are functions of `*mut T`, which is what is returned by `UnsafeCell::get()`
- jganetsk 6y agoI don't know that synchronizing with acquire-release is enough to make LLVM happy in this case. Mutable references are tagged with the LLVM noalias attribute. Rust language folks are very adamant about how wrong it is to end up with multiple aliases tagged with noalias. This is playing with fire.
- Arnavion 6y agoThere are no multiple aliases in the code presented in the blog post.
- jganetsk 6y agoOk you are right.
- steveklabnik 6y agoAlso UnsafeCell’s purpose in life is to make sure noalias is removed where appropriate.
- jganetsk 6y agoCan you explain that more? Because the requirement I pasted about having unique aliases does come from the UnsafeCell documentation. My understanding is that &mut still needs to be a unique alias even when it comes from an UnsafeCell.
- Arnavion 6y ago>My understanding is that &mut still needs to be a unique alias even when it comes from an UnsafeCell. That is correct. steveklabnik was not talking about this. UnsafeCell needs to prevent optimizations that reorder accesses to the `&mut` derived from its `*mut`. If reordering was allowed it could be possible that you write code that creates two `&mut` (or one `&mut` and one `&`) that appear to have distinct lifetimes (which ought to be well-defined) but are nevertheless reordered by the optimizer to overlap (which is aliasing, and thus UB). It also needs to disable the assumption that a `&Foo` is immutable if `Foo` is `UnsafeCell` or an aggregate that transitively contains `UnsafeCell`. This special behavior is why UnsafeCell is a lang item.
- steveklabnik 6y agoYes, the latter was what I was thinking of: use std::cell::UnsafeCell; pub fn no_unTsafecell(x: &i32) { } pub fn unsafecell(x: &UnsafeCell<i32>) { } gives define void @_ZN10playground14no_unTsafecell17hd5b10dbf031749b4E(i32* noalias nocapture readonly align 4 dereferenceable(4) %x) unnamed_addr #0 { define void @_ZN10playground10unsafecell17h3318292255a4201bE(i32* nocapture align 4 dereferenceable(4) %x) unnamed_addr #0 { thanks :)
- jganetsk 6y agoDoes it also help that the code doesn't actually cast the raw pointer to references? It only uses the read and write methods.
- Arnavion 6y agoNo. The write method also internally creates a borrow from the pointer.