-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Added Volatile Module. #12079
Added Volatile Module. #12079
Conversation
} | ||
} | ||
|
||
pub struct VolatilePtr<T> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we just have Volatile<T>
with priv data: T
, using the same technique as VolatileInt
VolatileBool
? (And then they would just be Volatile<int>
and Volatile<bool>
, etc.)
I guess having VolatilePtr<T>
too would be ok for external pointers, but...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I pushed a commit that changes it to that format.
I agree with @huonw that I'm second-guessing the layout of this module. I think that we should have @huonw has a good point in that if a major use case is interoping with something like memory-mapped I/O, the |
@alexcrichton @huonw Good points. I definitely think Would you want a single wrapping type |
@alexcrichton @huonw I removed the specific implementations such I still need to address @huonw last point. |
* | ||
* * `VolatileInt`: Provides semantics to work with valued integers. | ||
* * `VolatileBool`: Provides semantics to work with valued booleans. | ||
e * `VolatilePtr`: Provides semantics to work with pointers. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A stray e
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
@alexcrichton Ok, I removed |
* // Do something... | ||
* } | ||
* } | ||
* ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this example is a little too misleading. This makes it sound like all loop variables need to be volatile, but that's not true.
Volatile memory accesses are normally required when memory can change where the compiler has no way of knowing it can change. For example, if i
was a shared variable the compiler may assume that you were the only thread (and hence no one else could change it). Another case is memory-mapped I/O where the hardware may change the value each time you read it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@alexcrichton Well, I should probably clarify that in the example above, nothing in the program/loop was changing i
, thus, a compiler could assume it to be constant and factor the condition out, resulting in a static while true
. However, in a situation where volatile variables are useful (like you stated), something else might of changed i
.
Does that make sense?
@thehydroimpulse could you squash these commits? |
/// | ||
/// ``` | ||
/// let v: Volatile<int> = Volatile::new(10); | ||
/// static s: Volatile<bool> = Volatile { data: true }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This won't actually work because data
is private. Additionally, can you put this in a rust
code fence so it gets tested?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. Added the rust code fence.
@flaper87 Yes, I'll squash my commits after I make those changes. |
@flaper87 Squashed the commits. |
/*! | ||
* Volatile Module. | ||
* | ||
* The order of variables, and their execution isn't guaranteed. The compiler may |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"The order of execution of code is not guaranteed: the compiler may reorder statements and instructions to make things more efficient."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
@huonw Fixed, and squashed my commits. |
@alexcrichton review? |
I was thinking this through recently, and I was curious about how useful this type will be. Sorry I don't think I thought this through when this was initially opened. I would imagine that the purpose of this is to provide a form of safe wrapper around the intrinsics. You normally need volatile things when you have a form of memory which is changing beyond the knowledge of the compiler (I've only ever experienced volatile loads/stores with memory mapped I/O). With that in mind, and especially with rust's linear type system, I'm not sure what exactly you'd use a I've been thinking that something which may be useful is: fn volatile_load<T: Pod>(location: &T) -> T { ... }
fn volatile_store<T: Pod>(location: &mut T, t: T) { ... } But I think that I'd need to think this through more to make sure that this is a useful interface that we'd want. |
Making sure you don't accidentally access something non-volatile-ly. e.g. in C volatile int i;
// all accesses are volatile automatically but with only the wrappers for the intrinsics... the user has to remember to use them each time (i.e. remember to write |
@alexcrichton No worries. I think my initial goal was to allow an easier way to work with volatile variables. Previously, well, currently, you'd have to manually use the intrinsics whenever you touch the volatile variables. This is kind of a pain, especially compared to C. It's fairly easy to forget to call the intrinsics. Whereas if you'd have a type That's why I thought wrapping around the intrinsics would be somewhat useful. |
@huonw, I agree, but I'm having trouble thinking of a use case of a safely-shared I suppose I'm approaching this volatile type as a safe interface to the volatile intrinsics, but perhaps the interface can't be truly safe in all situations? |
@alexcrichton mmm. I'm trying to think of situations where we could have a safe volatile type (or where it'd be useful), but can't. Most of the volatile stuff I've done is with memory mapped I/O, and most of the stuff down there is inherently unsafe (mapping physical devices to memory, etc...). Thoughts? |
That was my reasoning behind a safe |
@alexcrichton So, the only real benefit Is that an appropriate benefit compared to the raw intrinsics? Or should we also include a safe |
The problem with |
On Tue, Feb 11, 2014 at 09:06:20AM -0800, Alex Crichton wrote:
I'm not sure that's true. There are some simple cases where I can |
On Tue, Feb 11, 2014 at 11:59:13AM -0800, Alex Crichton wrote:
I'm not sure I see the point. References like |
Any updates on where this is headed? @nikomatsakis @alexcrichton |
@alexcrichton @nikomatsakis Any final comment here? @thehydroimpulse could you rebase this PR ? |
@flaper87 Yep, I'll rebase. I'm also assuming it'd be best to remove it from the unstable module just like the other ones in there? Then just mark the module as unstable. |
I guess my willingness to merge depends on what happens if you try to do |
If it just results in a confusing error message, that's relatively ok and we can file a follow up bug. :) |
Error message, just for the sake of it:
|
@thehydroimpulse Did you figure out what's happening here? Also, this patch may need a rebase. If you're running short in time let us know. Probably someone can move this work forward. |
I think this should be implemented like Cell, using an Unsafe and taking &self for all operations, but using volatile_load/store instead of non-volatile (and restricted to single-word types, which however should include floating point and machine-supported SIMD types). And perhaps there should be a read-only and a write-only version, for read-only and write-only hardware registers. The use case is of course uncacheable memory-mapped devices; for cacheable memory, one should always use atomics instead. |
@flaper87 Yes. I'll be pushing my changes shortly. |
Yes this should definitely use |
@nikomatsakis Should I hold off until @flaper87's work lands? |
@thehydroimpulse I'd wait, yeah! FWIW, the patch will hopefully and this week. it's ready and I'm addressing some review feedback as we speak. In case you're interested / curious, this is the PR #12686 |
@thehydroimpulse the patch landed! You can now go ahead and rebase this one. Also, remember to make Volatile use |
@flaper87 Awesome. Thanks! |
@nikomatsakis I've addressed your previous comments (I guess they got deleted with a force push). I added the more constrained bounds (for i32 and u32 right now), used |
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to add #[allow(experimental)];
UPDATE: could you pls add a description about what this test does?
@thehydroimpulse thanks for the update here. I added few comments. Could you also squash these commits when you're done? Thanks a lot again for the great work here! |
* T is currently bound by the private VolatileSafe trait, which is only implemented for `i32` and `u32`. * Uses the volatile_load/volatile_store intrinsics. * User define-able types are not currently supported.
@flaper87 Addressed the comments and squashed my commits. |
Huh. So I realize I was thinking of something different when I thought of One thing is that this type should not be Share, as volatile loads and stores do not imply barriers, and it should use I'd like to see a realistic example that needs This has unfortunate interactions with our move semantics, in that if you export this pointer, and then move the value, weird things happen. It's kind of a borrow. Maybe we can better model it using an So long story short I'd like to understand better how this is to be used. |
Closing due to inactivity. I agree with @nikomatsakis, I think we need a compelling use case to guide this to make some more progress. |
fix: `signature_help`: use corresponding param list for methods Close rust-lang#12079
Fix some typos changelog: none
This is the second attempt at submitted the PR (wrecked the last one #12063 trying to squash my commits).
As per the discussion on the previous PR:
VolatilePtr
'sstore
method will achieve ownership of the current data first. This will zero-out the memory; after which the new pointer will be written. The old data is then dropped (through an explicitdrop
call).VolatilePtr.take
./cc @alexcrichton