How to prevent a user to modify the atomic?

For example I have a function:

fn test<F>(f: F) where F: Fn(&AtomicU32) {
    let i = AtomicU32::new(1);
    f(&i);
}

And I only want to the user to read the value of i, but cannot modify it:

test(|i| {
    i.fetch_add(1, Relaxed); // not allowed
})

Is there any way to do this? And for more generic, can I prevent user to modify a variable which has the "interior mutability"?

If both you and the user have shared access (&T) to a type with interior mutability, such as UnsafeCell, Mutex, or AtomicUsize, then there is no way for the user to not change the interior value. (Barring trivial methods such as ensuring that there is only one thread and taking away control flow from the user, or locking the mutex and dropping its guard).

The way I would tackle this scenario is to keep an AtomicU32, and a local u32. Anytime there's meaningful change to the local u32, you write to the AtomicU32. I'd also document that writing to the AtomicU32 does nothing, or I'd skip all of this outright and simply label it as a logical error (with the added modifiers as necessary, such as improperly modifying it would lead to UB, along with an unsafe marker as necessary).

In this callback-esque scenario, you could let the callback simply take updates by yielding u32s, rather than &AtomicU32s.

Thanks for suggesting. Using the Atomic is just for easy illustration, passing an immutable copy to user is not very appropriate in my case...

You can add your own wrapper struct with a private field:

pub struct AtomicWrapper(AtomicU32);

impl AtomicWrapper {
    pub fn get(&self) -> u32 {
        self.0.load(Ordering::SeqCst)
    }
}

Or if you only have a reference to begin with:

#[derive(Copy, Clone)]
pub struct AtomicRefWrapper<'a>(&'a AtomicU32);

impl AtomicRefWrapper<'_> {
    pub fn get(self) -> u32 {
        self.0.load(Ordering::SeqCst)
    }
}
5 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.