nanvm_lib/common/
ref_mut.rs1pub trait RefMut {
2 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}