remove GuardRegistration

Changed files
+58 -72
lifetime-guard
+7 -7
Cargo.lock
··· 4 5 [[package]] 6 name = "futures" 7 - version = "0.0.1" 8 dependencies = [ 9 "futures-combinators", 10 "futures-compat", ··· 15 16 [[package]] 17 name = "futures-combinators" 18 - version = "0.0.1" 19 dependencies = [ 20 "futures-core", 21 "futures-util", ··· 23 24 [[package]] 25 name = "futures-compat" 26 - version = "0.0.1" 27 dependencies = [ 28 "futures-core", 29 ] 30 31 [[package]] 32 name = "futures-core" 33 - version = "0.0.1" 34 35 [[package]] 36 name = "futures-derive" 37 - version = "0.0.1" 38 dependencies = [ 39 "proc-macro2", 40 "quote", ··· 43 44 [[package]] 45 name = "futures-util" 46 - version = "0.0.1" 47 dependencies = [ 48 "futures-core", 49 ] 50 51 [[package]] 52 name = "lifetime-guard" 53 - version = "0.0.1" 54 55 [[package]] 56 name = "proc-macro2"
··· 4 5 [[package]] 6 name = "futures" 7 + version = "0.0.2" 8 dependencies = [ 9 "futures-combinators", 10 "futures-compat", ··· 15 16 [[package]] 17 name = "futures-combinators" 18 + version = "0.0.2" 19 dependencies = [ 20 "futures-core", 21 "futures-util", ··· 23 24 [[package]] 25 name = "futures-compat" 26 + version = "0.0.2" 27 dependencies = [ 28 "futures-core", 29 ] 30 31 [[package]] 32 name = "futures-core" 33 + version = "0.0.2" 34 35 [[package]] 36 name = "futures-derive" 37 + version = "0.0.2" 38 dependencies = [ 39 "proc-macro2", 40 "quote", ··· 43 44 [[package]] 45 name = "futures-util" 46 + version = "0.0.2" 47 dependencies = [ 48 "futures-core", 49 ] 50 51 [[package]] 52 name = "lifetime-guard" 53 + version = "0.0.2" 54 55 [[package]] 56 name = "proc-macro2"
+8 -8
Cargo.toml
··· 3 members = [ "futures", "futures-core", "futures-combinators", "futures-compat", "futures-derive", "futures-util", "lifetime-guard"] 4 5 [workspace.package] 6 - version = "0.0.1" 7 rust-version = "1.87" 8 edition = "2024" 9 license = "MIT OR Apache-2.0" ··· 12 homepage = "https://github.com/AngleSideAngle/bcsc" 13 14 [workspace.dependencies] 15 - futures = { path = "futures", version = "0.0.1" } 16 - futures-combinators = { path = "futures-combinators", version = "0.0.1" } 17 - futures-compat = { path = "futures-compat", version = "0.0.1" } 18 - futures-core = { path = "futures-core", version = "0.0.1" } 19 - futures-derive = { path = "futures-derive", version = "0.0.1" } 20 - futures-util = { path = "futures-util", version = "0.0.1" } 21 - lifetime-guard = { path = "lifetime-guard", version = "0.0.1" }
··· 3 members = [ "futures", "futures-core", "futures-combinators", "futures-compat", "futures-derive", "futures-util", "lifetime-guard"] 4 5 [workspace.package] 6 + version = "0.0.2" 7 rust-version = "1.87" 8 edition = "2024" 9 license = "MIT OR Apache-2.0" ··· 12 homepage = "https://github.com/AngleSideAngle/bcsc" 13 14 [workspace.dependencies] 15 + futures = { path = "futures", version = "0.0.2" } 16 + futures-combinators = { path = "futures-combinators", version = "0.0.2" } 17 + futures-compat = { path = "futures-compat", version = "0.0.2" } 18 + futures-core = { path = "futures-core", version = "0.0.2" } 19 + futures-derive = { path = "futures-derive", version = "0.0.2" } 20 + futures-util = { path = "futures-util", version = "0.0.2" } 21 + lifetime-guard = { path = "lifetime-guard", version = "0.0.2" }
+5 -2
lifetime-guard/README.md
··· 13 let weak = pin::pin!(RefGuard::new()); 14 { 15 let strong = pin::pin!(ValueGuard::new(0)); 16 - strong.as_ref().registration().register(weak.as_ref()); 17 18 assert_eq!(strong.get(), 0); 19 assert_eq!(weak.get(), Some(0)); ··· 28 # Safety 29 30 You *may not* leak any instance of either `ValueGuard` or `RefGuard` to the 31 - stack using `mem::forget()` or any other mechanism that causes thier 32 contents to be overwritten without `Drop::drop()` running. 33 Doing so creates unsoundness that likely will lead to dereferencing a null 34 pointer. ··· 42 methods including `Box::leak()` because heap allocated data will never be 43 overwritten if it is never freed. 44
··· 13 let weak = pin::pin!(RefGuard::new()); 14 { 15 let strong = pin::pin!(ValueGuard::new(0)); 16 + weak.as_ref().register(strong.as_ref()); 17 18 assert_eq!(strong.get(), 0); 19 assert_eq!(weak.get(), Some(0)); ··· 28 # Safety 29 30 You *may not* leak any instance of either `ValueGuard` or `RefGuard` to the 31 + stack using `mem::forget()` or any other mechanism that causes their 32 contents to be overwritten without `Drop::drop()` running. 33 Doing so creates unsoundness that likely will lead to dereferencing a null 34 pointer. ··· 42 methods including `Box::leak()` because heap allocated data will never be 43 overwritten if it is never freed. 44 45 + The test cases for this library have been verified to not exhibit undefined 46 + behavior using [miri](https://github.com/rust-lang/miri). 47 +
+38 -55
lifetime-guard/src/lib.rs
··· 3 use std::{cell::Cell, marker::PhantomPinned, pin::Pin, ptr::NonNull}; 4 5 /// Strong guard for granting read access to a single interior mutable value to 6 - /// `RefGuard`. 7 /// 8 /// A `ValueGuard`:`RefGuard` relationship is exclusive, and behaves similarly 9 /// to a single `Rc` and `Weak` pair, but notably does not require heap 10 - /// allocation. `ValueGuard::registration` creates a `GuardRegistration`, which 11 - /// provides a movable wrapper for safety creating the circular references 12 - /// between two pinned self referential structs. 13 /// 14 /// # Safety 15 /// ··· 47 } 48 } 49 50 - /// Returns a `GuardRegistration`, which can be used to safety link `Self` 51 - /// to a `RefGuard`. 52 - #[inline] 53 - pub fn registration<'a>(self: Pin<&'a Self>) -> GuardRegistration<'a, T> { 54 - GuardRegistration { value_guard: self } 55 - } 56 - 57 /// Sets the internal value stored by `Self`. 58 #[inline] 59 pub fn set(&self, value: T) { ··· 86 87 /// Weak guard for acquiring read only access to a `ValueGuard`'s value. 88 /// 89 /// # Safety 90 /// 91 /// This struct *must* not be leaked to the stack using `mem::forget` or any ··· 111 _marker: PhantomPinned, 112 } 113 } 114 } 115 116 /// Helper function to invalidate a `RefGuard`'s `ValueGuard` reference ··· 146 } 147 } 148 149 - /// Safe api for creating self reference between a pinned `ValueGuard` and 150 - /// `RefGuard` pair. 151 - /// 152 - /// This can be acquired with 153 - /// [`ValueGuard::registration()`](ValueGuard::registration). 154 - pub struct GuardRegistration<'a, T> { 155 - value_guard: Pin<&'a ValueGuard<T>>, 156 - } 157 - 158 - impl<'a, T> GuardRegistration<'a, T> { 159 - /// Binds a provided `slot` to the `self.value_guard`. 160 - /// 161 - /// This means they will reference each other, and will invalidate their 162 - /// references to each other when dropped. 163 - /// 164 - /// This method also invalidates the existing references held by the 165 - /// now-replaced referencees of `slot` and `self.value_guard` to avoid 166 - /// dangling pointers. 167 - pub fn register(self, slot: Pin<&'a RefGuard<T>>) { 168 - // replace slot's value guard with reference to self.value_guard 169 - // and invalidate slot's old value guard if it exists 170 - if let Some(old_guard) = slot 171 - .value_guard 172 - .replace(Some(self.value_guard.get_ref().into())) 173 - { 174 - invalidate_value_guard(old_guard); 175 - } 176 - 177 - // replace self.value_guard's ref guard with reference to slot 178 - // and invalidate self.value_guard's old ref guard if it exists 179 - if let Some(old_guard) = self 180 - .value_guard 181 - .ref_guard 182 - .replace(Some(slot.get_ref().into())) 183 - { 184 - invalidate_ref_guard(old_guard); 185 - } 186 - } 187 - } 188 - 189 #[cfg(test)] 190 mod test { 191 use std::{mem, pin}; ··· 197 let weak = pin::pin!(RefGuard::new()); 198 { 199 let strong = pin::pin!(ValueGuard::new(2)); 200 - strong.as_ref().registration().register(weak.as_ref()); 201 202 assert_eq!(strong.get(), 2); 203 assert_eq!(weak.get(), Some(2)); ··· 216 let weak2 = pin::pin!(RefGuard::new()); 217 { 218 let strong = pin::pin!(ValueGuard::new(2)); 219 - strong.as_ref().registration().register(weak1.as_ref()); 220 221 assert_eq!(strong.get(), 2); 222 assert_eq!(weak1.get(), Some(2)); ··· 226 assert_eq!(weak1.get(), Some(3)); 227 228 // register next ptr, should invalidate previous weak ref (weak1) 229 - strong.as_ref().registration().register(weak2.as_ref()); 230 assert_eq!(weak1.get(), None); 231 assert_eq!(weak1.value_guard.get(), None); 232 ··· 247 fn safe_leak() { 248 let strong = Box::pin(ValueGuard::new(10)); 249 let weak = pin::pin!(RefGuard::new()); 250 - strong.as_ref().registration().register(weak.as_ref()); 251 252 // strong is now a ValueGuard on the heap that will never be freed 253 // this is sound because it will never be overwritten
··· 3 use std::{cell::Cell, marker::PhantomPinned, pin::Pin, ptr::NonNull}; 4 5 /// Strong guard for granting read access to a single interior mutable value to 6 + /// [`RefGuard`](RefGuard). 7 /// 8 /// A `ValueGuard`:`RefGuard` relationship is exclusive, and behaves similarly 9 /// to a single `Rc` and `Weak` pair, but notably does not require heap 10 + /// allocation. 11 /// 12 /// # Safety 13 /// ··· 45 } 46 } 47 48 /// Sets the internal value stored by `Self`. 49 #[inline] 50 pub fn set(&self, value: T) { ··· 77 78 /// Weak guard for acquiring read only access to a `ValueGuard`'s value. 79 /// 80 + /// Provides [`WeakGuard::register()`](Self::register) to register a `ValueGuard` 81 + /// to `Self` and vice versa. 82 + /// 83 /// # Safety 84 /// 85 /// This struct *must* not be leaked to the stack using `mem::forget` or any ··· 105 _marker: PhantomPinned, 106 } 107 } 108 + 109 + /// Binds a pinned `value_guard` to `self`. 110 + /// 111 + /// This means they will reference each other, and will invalidate their 112 + /// references to each other when dropped. 113 + /// 114 + /// This method also invalidates the existing references held by the 115 + /// now-replaced referencees of `self` and `value_guard` to avoid 116 + /// dangling pointers. 117 + pub fn register<'a>( 118 + self: Pin<&'a RefGuard<T>>, 119 + value_guard: Pin<&'a ValueGuard<T>>, 120 + ) { 121 + // replace input value_guard's ref guard with reference to self 122 + // and invalidate the old ref guard guard if it exists 123 + if let Some(old_guard) = 124 + value_guard.ref_guard.replace(Some(self.get_ref().into())) 125 + { 126 + invalidate_ref_guard(old_guard); 127 + } 128 + 129 + // replace self's value guard with reference to input value_guard 130 + // and invalidate self.value_guard's old ref guard if it exists 131 + if let Some(old_guard) = 132 + self.value_guard.replace(Some(value_guard.get_ref().into())) 133 + { 134 + invalidate_value_guard(old_guard); 135 + } 136 + } 137 } 138 139 /// Helper function to invalidate a `RefGuard`'s `ValueGuard` reference ··· 169 } 170 } 171 172 #[cfg(test)] 173 mod test { 174 use std::{mem, pin}; ··· 180 let weak = pin::pin!(RefGuard::new()); 181 { 182 let strong = pin::pin!(ValueGuard::new(2)); 183 + weak.as_ref().register(strong.as_ref()); 184 185 assert_eq!(strong.get(), 2); 186 assert_eq!(weak.get(), Some(2)); ··· 199 let weak2 = pin::pin!(RefGuard::new()); 200 { 201 let strong = pin::pin!(ValueGuard::new(2)); 202 + weak1.as_ref().register(strong.as_ref()); 203 204 assert_eq!(strong.get(), 2); 205 assert_eq!(weak1.get(), Some(2)); ··· 209 assert_eq!(weak1.get(), Some(3)); 210 211 // register next ptr, should invalidate previous weak ref (weak1) 212 + weak2.as_ref().register(strong.as_ref()); 213 assert_eq!(weak1.get(), None); 214 assert_eq!(weak1.value_guard.get(), None); 215 ··· 230 fn safe_leak() { 231 let strong = Box::pin(ValueGuard::new(10)); 232 let weak = pin::pin!(RefGuard::new()); 233 + weak.as_ref().register(strong.as_ref()); 234 235 // strong is now a ValueGuard on the heap that will never be freed 236 // this is sound because it will never be overwritten