Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add extra access methods for atomic types #1649

Merged
merged 2 commits into from
Aug 11, 2016

Conversation

Amanieu
Copy link
Member

@Amanieu Amanieu commented Jun 15, 2016

This RFC adds the following methods to atomic types:

  • get_mut
  • into_inner
  • as_raw
  • from_raw

Rendered

@durka
Copy link
Contributor

durka commented Jun 15, 2016

All the other methods for loading the values of atomic types take an argument to specify the ordering. Why not these?

@durka
Copy link
Contributor

durka commented Jun 15, 2016

What is required for code to be sound while calling the unsafe from_raw? Just a valid pointer or are there more invariants? If so why not take a reference and make it a safe fn? Same question for as_raw's return value, I guess.

@Amanieu
Copy link
Member Author

Amanieu commented Jun 15, 2016

All the other methods for loading the values of atomic types take an argument to specify the ordering. Why not these?

Because they are accessing the value non-atomically.

What is required for code to be sound while calling the unsafe from_raw?

The pointer needs to be valid, and you need to make sure that the other thread is not accessing the integer non-atomically while you are performing atomic operations on it.

The reason a raw pointer is used here is because the value is a shared and mutable integer, which can't be expressed using a reference.

@alexcrichton alexcrichton added the T-libs-api Relevant to the library API team, which will review and decide on the RFC. label Jun 20, 2016
@alexcrichton
Copy link
Member

The get_mut, into_inner, and as_raw methods seem good to me, but the from_raw method would basically tie our hands into always representing AtomicT as simply UnsafeCell<T>. This is likely to always be the case anyway, but it may mean that it'd be easier to just document that the two are the same and not worry about adding a method to do what to me seems at least a relatively rare operation.

@Amanieu
Copy link
Member Author

Amanieu commented Jun 27, 2016

@alexcrichton I think simply documenting that AtomicT has the same representation as T would also work fine. This is going to be used in unsafe code anyways, the only thing needed is a guarantee about the layout of atomic types.

@strega-nil
Copy link

Aren't there platforms where we'd have to use AtomicUsize to emulate smaller atomics?

@alexcrichton
Copy link
Member

@Amanieu yeah I might prefer to go that route (a function from *const T to &U seems kinda weird to me) and avoid the as_raw and from_raw methods. I think both are equivalent in terms of the practical and technical implications.

@ubsan yeah but AtomicU8 can always be byte-sized regardless of that, we'd just have to use usize-sized compare-and-swap operations to update the byte we care about (while ignoring all the other bytes)

@strega-nil
Copy link

@alexcrichton ah, 'k.

@glaebhoerl
Copy link
Contributor

@alexcrichton Hmm wouldn't that misbehave if you have like AtomicU8s in an array or such?

@Amanieu
Copy link
Member Author

Amanieu commented Jun 29, 2016

@glaebhoerl It isn't a problem since a modification to one AtomicU8 will simply cause a CAS on a nearby one to failed, which will just be retried.

@aturon aturon self-assigned this Jul 18, 2016
@aturon
Copy link
Member

aturon commented Jul 18, 2016

OK, after giving this RFC some though, I'm in favor of the general idea. In particular, I've wanted something like get_mut from time to time, for cases where I'm initializing an atomic data structure.

I personally would prefer to start with just get_mut, since into_inner is expressible in terms of it, but I don't feel too too strongly about that.

@Amanieu
Copy link
Member Author

Amanieu commented Jul 18, 2016

@aturon The reason for adding into_inner was to be able to consume an atomic that wasn't declared with a mutable binding. In practice I expect 99% of uses of get_mut to be inside drop which gives you a &mut anyways, so it wouldn't be too much of a loss to get rid of it.

@alexcrichton
Copy link
Member

🔔 This RFC is now entering its week-long final comment period 🔔

The libs team is leaning towards merging this as is (with get_mut and into_inner), but comments are always appreciated!

@alexcrichton alexcrichton added final-comment-period Will be merged/postponed/closed in ~10 calendar days unless new substational objections are raised. and removed I-nominated labels Jul 26, 2016
@alexcrichton
Copy link
Member

alexcrichton commented Aug 11, 2016

Discussed during libs triage the other day, the conclusion was to merge

Thanks again for the RFC @Amanieu!

Tracking issue

@alexcrichton alexcrichton merged commit c445f53 into rust-lang:master Aug 11, 2016
bors added a commit to rust-lang/rust that referenced this pull request Aug 19, 2016
@willmo
Copy link

willmo commented Sep 13, 2016

I still get an improper_ctypes warning when I try to use an atomic for FFI. Is this expected?

(Relative Rust noob here; apologies if this is a dumb question or an inappropriate place/way to comment.)

@nagisa
Copy link
Member

nagisa commented Sep 13, 2016

Atomic* are just your average Rust struct, which have unspecified layout, so the error is expected.

What this RFC is proposing is ability to extract plain isize from your AtomicIsize, which you can then put into any of your FFI structs. Alas, the functionality in question does not exist yet, because even though this RFC is accepted, the corresponding functionality is not implemented. You can track the implementation on the tracking issue.

@Amanieu
Copy link
Member Author

Amanieu commented Sep 13, 2016

Actually, it has already been implemented: rust-lang/rust#35719

@willmo
Copy link

willmo commented Sep 18, 2016

@nagisa, it seems to me that with this RFC the layout of Atomic* is now specified:

It also specifies that the layout of an AtomicT type is always the same as the underlying T type. So, for example, AtomicI32 is guaranteed to be transmutable to and from i32.

But the compiler has no way of knowing this.

Apologies that this wasn't clear from my earlier example, but as in the example of Linux futexes, I need to have Rust atomically manipulate a value shared with C. So it seems like the correct solution is a pointer cast, and the effect of this RFC is that this is now defined/correct? (That's another contrived example, but closer to what I need to do.)

But this is not nearly as nice as being able to use Atomic* directly in my #[repr(C)] struct. For one thing, aside from visibility (which I would certainly use in a real example), nothing forces me to manipulate the field atomically. In fact, manipulating it non-atomically (incorrectly) is easy and involves no unsafe, while manipulating it atomically (correctly) requires much more typing and use of unsafe.

I can't even use UnsafeCell<isize>, which would at least force me to use unsafe and indicate to the compiler that my struct has interior mutability, because UnsafeCell is not #[repr(C)]. Nor should it be, of course. But it would be super cool if UnsafeCell had some kind of #[repr(inherit)] or something, that would allow UnsafeCell<T> to be used in a #[repr(C)] struct iff T could be used in a #[repr(C)] struct.

@Amanieu
Copy link
Member Author

Amanieu commented Sep 18, 2016

My opinion is that structs with only a single member should be defined as having the same representation as that element.

As a workaround, I guess we could just mark the atomic types as #[repr(C)] for now and ignore the warning about UnsafeCell not being #[repr(C)].

willmo added a commit to willmo/rust that referenced this pull request Jul 8, 2018
This allows them to be used in #[repr(C)] structs without warnings. Since rust-lang/rfcs#1649 and rust-lang#35603 they are already documented to have "the same in-memory representation as" their corresponding primitive types. This just makes that explicit.
Mark-Simulacrum added a commit to Mark-Simulacrum/rust that referenced this pull request Jul 10, 2018
Add #[repr(transparent)] to Atomic* types

This allows them to be used in `#[repr(C)]` structs without warnings. Since rust-lang/rfcs#1649 and rust-lang#35603 they are already documented to have "the same in-memory representation as" their corresponding primitive types. This just makes that explicit.

This was briefly part of rust-lang#51395, but was controversial and therefore dropped. But it turns out that it's essentially already documented (which I had forgotten).
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this pull request Jul 10, 2018
Add #[repr(transparent)] to Atomic* types

This allows them to be used in `#[repr(C)]` structs without warnings. Since rust-lang/rfcs#1649 and rust-lang#35603 they are already documented to have "the same in-memory representation as" their corresponding primitive types. This just makes that explicit.

This was briefly part of rust-lang#51395, but was controversial and therefore dropped. But it turns out that it's essentially already documented (which I had forgotten).
@Centril Centril added A-sync Synchronization related proposals & ideas A-sync-atomics Atomics related proposals & ideas labels Nov 23, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-sync Synchronization related proposals & ideas A-sync-atomics Atomics related proposals & ideas final-comment-period Will be merged/postponed/closed in ~10 calendar days unless new substational objections are raised. T-libs-api Relevant to the library API team, which will review and decide on the RFC.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants