nanvm_lib/common/
ref_mut.rs

1pub trait RefMut {
2    // a better name is `as_mut_ptr` but it's already used by `Slice`.
3    unsafe fn to_mut_ptr(&mut self) -> *mut Self {
4        self as _
5    }
6    fn modify(&mut self, f: impl FnOnce(Self) -> Self)
7    where
8        Self: Sized,
9    {
10        unsafe {
11            let p = self.to_mut_ptr();
12            p.write(f(p.read()));
13        };
14    }
15}
16
17impl<T> RefMut for T {}
18
19#[cfg(test)]
20mod test {
21    use core::sync::atomic::{AtomicIsize, Ordering};
22
23    use wasm_bindgen_test::wasm_bindgen_test;
24
25    use super::*;
26
27    struct A<'a>(i32, &'a AtomicIsize);
28
29    impl Drop for A<'_> {
30        fn drop(&mut self) {
31            self.1.fetch_add(1, Ordering::Relaxed);
32        }
33    }
34
35    #[test]
36    #[wasm_bindgen_test]
37    fn test_move_update() {
38        let x = AtomicIsize::new(0);
39        {
40            let mut a = A(5, &x);
41            let mut i = 0;
42            a.modify(|mut a| {
43                a.0 += 1;
44                i += 1;
45                a
46            });
47            assert_eq!(a.0, 6);
48            assert_eq!(i, 1);
49            assert_eq!(x.load(Ordering::Relaxed), 0);
50            a.modify(|a| A(a.0 - 2, a.1));
51            assert_eq!(a.0, 4);
52            assert_eq!(x.load(Ordering::Relaxed), 1);
53        }
54        assert_eq!(x.load(Ordering::Relaxed), 2);
55    }
56}