rust-osdev/volatile

Best of both worlds API?

coolreader18 opened this issue · 5 comments

I think there's a way to combine the APIs of 0.3 and 0.4, to be able to have both easy volatile references as well as a substitute for C's volatile typ var; variable declarations (which I was primarily using volatile 0.3 for). I'm imagining something similar to this:

pub struct VolatileRef<R, A> {
    reference: R,
    access: PhantomData<A>,
}
// same as current Volatile functions, except for below name changes
impl<R> VolatileRef<R, ReadWrite> {
    // or maybe from_ref?
    pub const fn new_ref(reference: R) -> Self;
}
impl<R> VolatileRef<R, ReadOnly> {
    pub const fn new_ref_read_only(reference: R) -> Self;
}
impl<R> VolatileRef<R, WriteOnly> {
    pub const fn new_ref_write_only(reference: R) -> Self;
}

// not sure about the name. S for SimpleBox/StackBox, or maybe could do VBox?
#[repr(transparent)]
pub struct SBox<T: ?Sized>(T);

pub type Volatile<T, A> = VolatileRef<SBox<T>, A>;

impl<T> Volatile<T> {
    pub const fn new(value: T) -> Self;
}
impl<T> Volatile<T, ReadOnly> {
    pub const fn new_read_only(value: T) -> Self;
}
impl<T> Volatile<T, WriteOnly> {
    pub const fn new_write_only(value: T) -> Self;
}

I'm totally not sold on any of the naming, but I think the basic idea of Volatile<T, A>/VolatileRef<R, A> is pretty good.

Could you give more details about your use case? I also thought about providing both Volatile and VolatileRef, but most use cases I thought of could be implemented with VolatileRef, so I decided against this approach in order to make the API less complex.

The problem with the value-based Volatile type is that it's easy to misuse it. For example, it's easy to accidentally move it in memory, so that it does no longer point to the original memory address. You also can easily create stack-based volatile types with it, which doesn't make much sense. The new API makes it much clearer that the volatile operation corresponds to a specific memory location.

I'm using volatile to avoid compiler optimizations for a timing-safe compare operation. I actually am specifically creating stack-based volatile types 😅. I definitely think the current API makes a lot more sense for the more common use of volatile for interacting with syscalls or whatever you OS devs do :), but I guess I'm here to say that there was at least one person who was using 0.3 for stack-based volatiles.

That's a pretty cool way to use volatile and also a totally valid reason to use volatile in combination with stack-based values. However, I don't think that this use case is common, so I'm inclined to leave the API as is for now.

There are alternatives to this crate though. For example, the vcell crate provides a VolatileCell with a similar API as we had, the only difference is that it requires only &self references for write. If that doesn't work for you, I'd be happy to re-release version 0.3 in a separate crate, e.g. named volatile-value that specifically focuses on use-cases like yours.

Oh, I hadn't seen that crate before! I'll probably switch to that, thanks for your help.

Great to hear that. Just let me know if it doesn't work for you, then we find a different solution.