-
Notifications
You must be signed in to change notification settings - Fork 19
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
Rewrite crate to operate on reference values #13
Conversation
Also: minor improvements
These methods are only available on nightly since the required functions of `core::intrinsics` are still unstable.
This makes wrapping struct fields in Volatile a lot more complicated doesn't it? Previously one could write something like this: #[repr(C)]
struct HardwareMemoryMappedFoo {
bar: Volatile<u32>,
baz: Volatile<u16>,
} ig it's still possible to just take references to each field individually, but that seems needlesly complicated. i still like the idea of taking a reference though. perhaps this could be solved by making two different Volatile types |
Good point! Two different types sound like a good solution. |
After thinking a bit more about this, I think a better solution is to add a The drawback is that the |
I pushed a new version with an implementation of the |
The `fill` method is only support for `u8` slices because there is no intrinsic for volatile memset with a generic type `T`.
I decided to merge this for now. The new implementation is already much more powerful than the old and I think the struct access problem is also resolved with the new |
Maybe it would be better to have a Volatile wrapper for values and another wrapper like |
See #15 for some discussion about this. I'm aware that this was a breaking change and requires restructuring your code. However, I don't think that there are common use cases that only work with the old API, so I decided against adding an additional value-based type. Since the version number was increased to |
Is there an easy way to do the following #[repr(C)]
struct myStruct {
rwValue: Volatile<u8>,
rValue: Volatile<u8, ReadOnly>
} where you have a mix of different access controls for the struct members? I'm aware of the map method but this would not work if you directly used Volatile::new() on a struct right? The new() (or new_read_only, etc) method will create a Volatile struct with all the inner values having the same second generic parameter A used in PhantomData correct*? It definitely is not a big deal, just a question on ergonomics. I can always fall back to just using RW as a default. Edit: |
@zyklotomic I just created to #19 to add methods to restrict access. With this you could do something like trait MyStructAccess {
fn rValue(&self) -> Volatile<&u8, volatile::access::ReadOnly>;
}
impl MyStructAccess for Volatile<&mut myStruct> {
fn rValue(&self) -> Volatile<&u8, volatile::access::ReadOnly> {
self.map(|s| &s.rValue).read_only()
}
} Or you could add a custom Would this work for you? |
Yup that works! I also came to the conclusion that I would have to move the access abstraction to a secondary getter/setter interface and expose methods accordingly, but I like the way your PR handles it even more since it removes The second option sounds good too, time will tell if people like using that too, but the PR one feels cleaner imo. I also wanted to say thanks for all your dedication to this crate (as well as to blog_os). I really appreciate it as your resources have been invaluable to me as a student. |
Great to hear that! :) |
I am pretty sure this PR is incorrect. References are marked by rustc as https://llvm.org/docs/LangRef.html#parameter-attributes
In addition for immutable references passed as argument the I think you can solve this problem by requiring an |
@bjorn3 Thanks a lot for voicing your concerns! I think you're right that we should avoid using reference when operating on volatile values. I'm not sure how LLVM prioritizes between volatile operations and noalias/defereferencable attributes (e.g. does it still keep all volatile loads/stores even for I started to create an |
This PR rewrites the crate completely. Instead of wrapping the value directly, we now wrap a reference. This way, we can implement volatile operations on slices, which is for example important for operating on pixel-based framebuffers since writing each pixel individually would be to slow (the compiler is not allowed to combine multiple volatile writes).
Since some methods require unstable features and thus only work on nightly, this PR also introduces a cargo feature named
unstable
. This way, users can opt-in to the unstable functionality if they like, but otherwise this crate works fine on stable (without the slice methods).