add ValueGuard test

Changed files
+45 -66
lifetime-guard
src
+45 -66
lifetime-guard/src/lib.rs
··· 1 1 /// Unsound Drop based guard API 2 2 use std::{ 3 3 cell::Cell, 4 - mem, 5 - pin::{Pin, pin}, 6 - ptr::{self, NonNull, dangling}, 4 + marker::PhantomPinned, 5 + pin::Pin, 6 + ptr::{self}, 7 7 }; 8 8 9 - /// must not outlive strong guard 10 - /// 11 - /// enforces strong guard doesn't move with ptr 12 - pub struct WeakGuard<'weak, T> { 13 - strong: Option<&'weak StrongGuard<'weak, T>>, 14 - } 15 - 16 - impl<'weak, T> WeakGuard<'weak, T> { 17 - pub fn register_strong(&mut self, weak: &'weak T) { 18 - self.strong = Some(weak); 19 - } 20 - } 21 - 22 - impl<'weak, T> Drop for WeakGuard<'weak, StrongGuard<'weak, T>> { 23 - fn drop(&mut self) { 24 - // self.weak. 25 - } 26 - } 27 - 28 - /// outlives strong guard 29 - pub struct StrongGuard<'weak, T> { 30 - strong: *const WeakGuard<'weak, T>, 31 - } 32 - 33 - // wakers must outlive 'task 34 - impl<'weak, T> StrongGuard<'weak, T> { 35 - pub fn new(strong: *const WeakGuard<'weak, T>) -> Self { 36 - Self { 37 - strong: task.into(), 38 - } 39 - } 40 - } 41 - 42 - // pub struct GuardRegistration<'weak, T> { 43 - // task: &'weak StrongGuard<'weak, T>, // valid for all of 'weak 44 - // } 45 - 46 - // impl<'weak> GuardRegistration<'weak> { 47 - // // slot is valid for all 'weak 48 - // pub fn register(self, slot: &'weak mut StrongGuard<'weak>) { 49 - // // Cast from 'weak to 'static 50 - // // 51 - // // # Safety 52 - // // 53 - // // This is safe because the drop guard guarantees that the task ptr (which lives for static) 54 - // // becomes null when the wake is dropped, ensuring the dangling pointer is never dereferenced. 55 - // let dangling_task = unsafe { 56 - // mem::transmute::< 57 - // &'weak dyn StrongGuard<'weak>, 58 - // *const dyn StrongGuard<'weak>, 59 - // >(self.task) 60 - // }; 61 - // slot.strong = dangling_task; 62 - 63 - // (*self.task).register_waker(slot); 64 - // } 65 - // } 66 - 67 9 pub struct ValueGuard<T> { 68 10 data: T, 69 11 ref_guard: Cell<*const RefGuard<T>>, 12 + _marker: PhantomPinned, 70 13 } 71 14 72 15 impl<T> ValueGuard<T> { ··· 74 17 Self { 75 18 data, 76 19 ref_guard: Cell::new(ptr::null()), 20 + _marker: PhantomPinned, 77 21 } 22 + } 23 + 24 + pub fn registration<'a>(self: Pin<&'a Self>) -> GuardRegistration<'a, T> { 25 + GuardRegistration { value_guard: self } 78 26 } 79 27 80 28 pub fn set(&mut self, value: T) { ··· 101 49 102 50 pub struct RefGuard<T> { 103 51 value_guard: Cell<*const ValueGuard<T>>, 52 + _marker: PhantomPinned, 104 53 } 105 54 106 55 impl<T> RefGuard<T> { 107 56 pub fn new() -> Self { 108 57 Self { 109 58 value_guard: Cell::new(ptr::null()), 59 + _marker: PhantomPinned, 110 60 } 111 61 } 112 62 } ··· 133 83 Self { value_guard } 134 84 } 135 85 136 - pub fn register(self, slot: Pin<&'a mut RefGuard<T>>) { 86 + pub fn register(self, slot: Pin<&'a RefGuard<T>>) { 137 87 // register new ptrs 138 88 let old_value_guard = slot 139 89 .value_guard 140 90 .replace(self.value_guard.get_ref() as *const ValueGuard<T>); 141 91 142 - let old_ref_guard = self 143 - .value_guard 144 - .ref_guard 145 - .replace(slot.into_ref().get_ref()); 92 + let old_ref_guard = self.value_guard.ref_guard.replace(slot.get_ref()); 146 93 147 94 // annul old ptrs 148 95 unsafe { old_value_guard.as_ref() } ··· 151 98 .inspect(|guard| guard.value_guard.set(ptr::null())); 152 99 } 153 100 } 101 + 102 + #[cfg(test)] 103 + mod test { 104 + use std::pin; 105 + 106 + use super::*; 107 + 108 + fn consume<T>(input: T) {} 109 + 110 + #[test] 111 + fn basic() { 112 + let weak = RefGuard::new(); 113 + let weak_pinned = pin::pin!(weak); 114 + { 115 + let mut strong = ValueGuard::new(2); 116 + let mut strong_pinned = pin::pin!(strong); 117 + strong_pinned 118 + .as_ref() 119 + .registration() 120 + .register(weak_pinned.as_ref()); 121 + 122 + assert_eq!(strong_pinned.get(), 2); 123 + assert_eq!(weak_pinned.get(), Some(2)); 124 + 125 + unsafe { strong_pinned.as_mut().get_unchecked_mut() }.set(3); 126 + assert_eq!(strong_pinned.get(), 3); 127 + assert_eq!(weak_pinned.get(), Some(3)); 128 + } 129 + 130 + assert_eq!(weak_pinned.get(), None); 131 + } 132 + }