Realtime safe, waitfree, concurrency library

cleanup

Changed files
+13 -20
src
+10 -18
src/lib.rs
··· 49 50 /// this function never blocks. (`fetch_update` loop doesn't count) 51 pub fn lock(&mut self) -> ReadGuard<'_, T> { 52 - let shared_ref = self.shared_ref(); 53 - 54 ReadGuard { 55 - shared: shared_ref, 56 - value: shared_ref.lock_read(), 57 - reader: PhantomData, 58 } 59 } 60 } ··· 75 /// Doesn't implement Clone as that would require refcounting to know when to unlock. 76 #[derive(Debug)] 77 pub struct ReadGuard<'a, T> { 78 - shared: &'a Shared<T>, 79 - value: Ptr, 80 - /// `PhantomData` makes the borrow checker prove that there only ever is one `ReadGuard`. 81 - /// This allows resetting the readstate without some kind of counter 82 - reader: PhantomData<&'a mut Reader<T>>, 83 } 84 85 impl<T> Deref for ReadGuard<'_, T> { 86 type Target = T; 87 88 fn deref(&self) -> &Self::Target { 89 - // SAFETY: ReadGuard was created, so the Writer knows not to write in this spot 90 - unsafe { self.shared.get_value_ref(self.value) } 91 } 92 } 93 ··· 101 } 102 } 103 104 - // /// SAFETY: behaves like a ref to T. https://doc.rust-lang.org/std/marker/trait.Sync.html 105 - // unsafe impl<T: Sync> Send for ReadGuard<'_, T> {} 106 - // /// SAFETY: behaves like a ref to T. https://doc.rust-lang.org/std/marker/trait.Sync.html 107 - // unsafe impl<T: Sync> Sync for ReadGuard<'_, T> {} 108 - 109 impl<T> Drop for ReadGuard<'_, T> { 110 fn drop(&mut self) { 111 // release the read lock 112 - self.shared.release_read_lock(); 113 } 114 } 115 ··· 250 /// Dropping this makes all changes available to the Reader. 251 #[derive(Debug)] 252 pub struct WriteGuard<'a, T, O> { 253 writer: &'a mut Writer<T, O>, 254 } 255
··· 49 50 /// this function never blocks. (`fetch_update` loop doesn't count) 51 pub fn lock(&mut self) -> ReadGuard<'_, T> { 52 + // SAFETY: value just locked 53 + let value = unsafe { &*self.shared_ref().lock_read().get() }; 54 ReadGuard { 55 + value, 56 + reader: self, 57 } 58 } 59 } ··· 74 /// Doesn't implement Clone as that would require refcounting to know when to unlock. 75 #[derive(Debug)] 76 pub struct ReadGuard<'a, T> { 77 + reader: &'a Reader<T>, 78 + value: &'a T, 79 } 80 81 impl<T> Deref for ReadGuard<'_, T> { 82 type Target = T; 83 84 fn deref(&self) -> &Self::Target { 85 + self.value 86 } 87 } 88 ··· 96 } 97 } 98 99 impl<T> Drop for ReadGuard<'_, T> { 100 fn drop(&mut self) { 101 // release the read lock 102 + self.reader.shared_ref().release_read_lock(); 103 } 104 } 105 ··· 240 /// Dropping this makes all changes available to the Reader. 241 #[derive(Debug)] 242 pub struct WriteGuard<'a, T, O> { 243 + // can't hold a mut ref to T, as then it wouldn't be possible to write to both at the same time, 244 + // which is an optimization i want to keep. 245 writer: &'a mut Writer<T, O>, 246 } 247
+3 -2
src/shared.rs
··· 115 } 116 117 impl<T> Shared<T> { 118 - pub(crate) fn lock_read(&self) -> Ptr { 119 // fetch update loop could be replaced with: 120 // - set read state to both 121 // - read read ptr ··· 131 // SAFETY: fetch_update closure always returns Some, so the result is alwyays Ok 132 let result = unsafe { result.unwrap_unchecked() }; 133 // result is the previous value, so the read_state isn't set, only the read_ptr 134 - State::new(result).read_ptr() 135 } 136 137 pub(crate) fn release_read_lock(&self) {
··· 115 } 116 117 impl<T> Shared<T> { 118 + pub(crate) fn lock_read(&self) -> &UnsafeCell<T> { 119 // fetch update loop could be replaced with: 120 // - set read state to both 121 // - read read ptr ··· 131 // SAFETY: fetch_update closure always returns Some, so the result is alwyays Ok 132 let result = unsafe { result.unwrap_unchecked() }; 133 // result is the previous value, so the read_state isn't set, only the read_ptr 134 + let ptr = State::new(result).read_ptr(); 135 + self.get_value(ptr) 136 } 137 138 pub(crate) fn release_read_lock(&self) {