old school music tracker audio backend

Arc removed and replaced with custom system. Way more granular and better Send and Sync bounds

luca3s 36b6803b 7c0f3055

+297 -174
+61 -19
simple-left-right/src/inner.rs
··· 1 - use core::{cell::UnsafeCell, hint::unreachable_unchecked, sync::atomic::AtomicU8}; 1 + use core::{ 2 + cell::UnsafeCell, hint::unreachable_unchecked, mem::MaybeUninit, sync::atomic::{self, AtomicU8, Ordering} 3 + }; 2 4 3 5 #[derive(PartialEq, Eq, Clone, Copy, Debug)] 4 6 pub(crate) enum Ptr { ··· 23 25 _ => unsafe { unreachable_unchecked() }, 24 26 } 25 27 } 26 - 27 - /// ignores potentially set read bits. 28 - /// SAFETY: no bits except the for bottom three can be set 29 - pub(crate) unsafe fn from_u8_ignore_read(value: u8) -> Self { 30 - match value & 0b100 { 31 - 0b000 => Self::Value1, 32 - 0b100 => Self::Value2, 33 - // SAFETY: unsafe fn. communicated in docs 34 - _ => unsafe { unreachable_unchecked() }, 35 - } 36 - } 37 28 } 38 29 39 30 #[derive(Debug)] ··· 52 43 } 53 44 } 54 45 55 - /// SAFETY: only the read state bits are set 46 + /// SAFETY: needs to be the internal state u8. 56 47 pub(crate) unsafe fn from_u8_ignore_ptr(value: u8) -> Self { 57 48 match value & 0b011 { 58 49 0b00 => Self::None, ··· 79 70 /// bit 1: is value 2 being read 80 71 /// bit 3: which value should be read next (0: value 1, 1: value 2) 81 72 pub state: AtomicU8, 73 + pub access_count: AtomicU8, 82 74 } 83 75 84 - /// SAFETY: Shared not public. Reader and Writer make it safe to use. Same restrictions as RwLock, which allows similar access 85 - unsafe impl<T: Send> Send for Shared<T> {} 86 - 87 - /// SAFETY: Shared not public. Reader and Writer make it safe to use. Same restrictions as RwLock, which allows similar access 88 - unsafe impl<T: Send + Sync> Sync for Shared<T> {} 89 - 90 76 impl<T> Shared<T> { 77 + /// initializes everything except for both values. 78 + pub(crate) fn initialize_state(this: &mut MaybeUninit<Self>) { 79 + // SAFETY: takes &mut self, so no writing is okay 80 + unsafe { 81 + (&raw mut (*this.as_mut_ptr()).access_count).write(AtomicU8::new(1)); 82 + (&raw mut (*this.as_mut_ptr()).state).write(AtomicU8::new(0b000)); 83 + } 84 + } 85 + 91 86 pub(crate) fn get_value(&self, ptr: Ptr) -> &UnsafeCell<T> { 92 87 match ptr { 93 88 Ptr::Value1 => &self.value_1, 94 89 Ptr::Value2 => &self.value_2, 95 90 } 91 + } 92 + 93 + /// If self is unique increase the count and returns true. 94 + /// Otherwise returns false. 95 + /// 96 + /// If this returns true another smart pointer has to be created otherwise memory will be leaked 97 + pub(crate) unsafe fn is_unique_with_increase(&self) -> bool { 98 + // Relaxed taken from std Arc 99 + let old_access = self.access_count.load(Ordering::Acquire); 100 + debug_assert!( 101 + old_access <= 2, 102 + "at maximum there is one Reader and one Writer" 103 + ); 104 + if old_access == 1 { 105 + self.access_count.fetch_add(1, Ordering::Relaxed); 106 + true 107 + } else { 108 + false 109 + } 110 + } 111 + 112 + /// decreases the access_count and returns if self should now be dropped. 113 + /// 114 + /// | return | needed reaction 115 + /// |---|---| 116 + /// | true | self needs to be dropped or memory is leaked | 117 + /// | false | this ptr to self could now become dangling at any time | 118 + /// 119 + /// dropping self when this returns true is safe and needed synchronisation has been done. 120 + pub(crate) unsafe fn should_drop(&self) -> bool { 121 + let old_access = self.access_count.fetch_sub(1, Ordering::Release); 122 + debug_assert!( 123 + old_access <= 2, 124 + "at maximum there is one Reader and one Writer" 125 + ); 126 + if old_access != 1 { 127 + return false; 128 + } 129 + // see std Arc 130 + atomic::fence(Ordering::Acquire); 131 + true 132 + } 133 + 134 + pub(crate) fn is_unique(&self) -> bool { 135 + let access = self.access_count.load(Ordering::Acquire); 136 + debug_assert!(access <= 2, "at maximum there is one Reader and one Writer"); 137 + access == 1 96 138 } 97 139 }
+236 -155
simple-left-right/src/lib.rs
··· 31 31 use std::thread; 32 32 33 33 use core::{ 34 - cell::UnsafeCell, 35 - marker::PhantomData, 36 - mem::MaybeUninit, 37 - ops::Deref, 38 - sync::atomic::{fence, AtomicU8, Ordering}, 34 + cell::UnsafeCell, marker::PhantomData, mem::MaybeUninit, ops::Deref, ptr::NonNull, sync::atomic::{fence, AtomicU8, Ordering} 39 35 }; 40 36 41 - use alloc::{collections::vec_deque::VecDeque, sync::Arc}; 37 + use alloc::{collections::vec_deque::VecDeque, boxed::Box}; 42 38 43 39 mod inner; 44 40 ··· 50 46 fn absorb(&mut self, operation: O); 51 47 } 52 48 53 - /// Data won't change while holding the Guard. This also means the Writer can only issue one swap, while Guard is being held 54 - #[derive(Debug)] 55 - pub struct ReadGuard<'a, T> { 56 - data: &'a T, 57 - state: &'a AtomicU8, 58 - // PhantomData makes the borrow checker prove that there only ever is one ReadGuard 59 - // 60 - // This is needed because setting the ReadState can only be reset when no ReadGuard exists 61 - // and that would mean some kind of counter 62 - reader: PhantomData<&'a mut Reader<T>>, 63 - } 64 - 65 - // only struct that should have this impl, as it doesn't have any methods 66 - impl<'a, T> Deref for ReadGuard<'a, T> { 67 - type Target = T; 68 - 69 - fn deref(&self) -> &Self::Target { 70 - self.data 71 - } 72 - } 73 - 74 - impl<T, E> AsRef<E> for ReadGuard<'_, T> 75 - where 76 - E: ?Sized, 77 - T: AsRef<E>, 78 - { 79 - fn as_ref(&self) -> &E { 80 - self.deref().as_ref() 81 - } 82 - } 83 - 84 - impl<T> Drop for ReadGuard<'_, T> { 85 - fn drop(&mut self) { 86 - // release the read lock 87 - self.state.fetch_and(0b100, Ordering::Release); 88 - } 89 - } 90 - 91 49 /// Dropping the Reader isn't realtime safe, because if dropped after the Writer, it deallocates. 92 50 /// Should only get dropped, when closing the real-time thread 93 51 /// 94 52 /// Reader will be able to read data even if Writer has been dropped. Obviously that data won't change anymore 95 - /// When there is no Reader the Writer is able to create a new one. The other way around doesn't work 53 + /// When there is no Reader the Writer is able to create a new one. The other way around doesn't work. 54 + /// 55 + /// Isn't Sync as there is no methos that takes &self, so it is useless anyways. 96 56 #[derive(Debug)] 97 57 pub struct Reader<T> { 98 - inner: Arc<Shared<T>>, 58 + shared: NonNull<Shared<T>>, 59 + /// for drop check 60 + _own: PhantomData<Shared<T>>, 99 61 } 100 62 101 63 impl<T> Reader<T> { 64 + const fn shared_ref(&self) -> &Shared<T> { 65 + // SAFETY: Reader always has a valid Shared<T>, a mut ref to a shared is never created, 66 + // only to the UnsafeCell<T>s inside of it 67 + unsafe { self.shared.as_ref() } 68 + } 69 + 102 70 /// this function never blocks. (`fetch_update` loop doesn't count) 103 71 pub fn lock(&mut self) -> ReadGuard<'_, T> { 72 + let inner_ref = self.shared_ref(); 104 73 // sets the corresponding read bit to the write ptr bit 105 74 // happens as a single atomic operation so the 'double read' state isn't needed 106 75 // ptr bit doesnt get changed 107 76 // always Ok, as the passed closure never returns None 108 77 let update_result = 109 - self.inner 78 + inner_ref 110 79 .state 111 80 .fetch_update(Ordering::Relaxed, Ordering::Acquire, |value| { 112 81 // SAFETY: At this point no Read bit is set, as creating a ReadGuard requires a &mut Reader and the Guard holds the &mut Reader ··· 122 91 // we continue working with the state that we set. 123 92 124 93 // SAFETY: the passed closure always returns Some, so fetch_update never returns Err 125 - let ptr = unsafe { 126 - // here it doesn't matter if we create the Ptr from the read bits or from the ptr bit, as they match 127 - Ptr::from_u8_ignore_read(update_result.unwrap_unchecked()) 128 - }; 94 + let ptr = unsafe { Ptr::from_u8_no_read(update_result.unwrap_unchecked()) }; 129 95 130 96 // SAFETY: the Writer allowed the read on this value because the ptr bit was set. The read bit has been set 131 - let data = unsafe { self.inner.get_value(ptr).get().as_ref().unwrap_unchecked() }; 97 + let data = unsafe { inner_ref.get_value(ptr).get().as_ref().unwrap_unchecked() }; 132 98 133 99 ReadGuard { 134 100 data, 135 - state: &self.inner.state, 101 + state: &inner_ref.state, 136 102 reader: PhantomData, 137 103 } 138 104 } 139 105 } 140 106 141 - // Don't ever create a WriteGuard directly 142 - /// Can be used to write to the Data structure. 143 - /// 144 - /// When this structure exists the Reader already switched to the other value 145 - /// 146 - /// Dropping this makes all changes available to the Reader 147 - #[derive(Debug)] 148 - pub struct WriteGuard<'a, T, O> { 149 - writer: &'a mut Writer<T, O>, 150 - } 107 + /// SAFETY: Owns a T 108 + unsafe impl<T: Send> Send for Reader<T> {} 151 109 152 - impl<T, O> WriteGuard<'_, T, O> { 153 - /// Makes the changes available to the reader. 154 - pub fn swap(self) {} 155 - 156 - /// Gets the value currently being written to. 157 - pub fn read(&self) -> &T { 158 - self.writer.read() 159 - } 160 - 161 - /// Isn't public as this could easily create disconnects between the two versions. 162 - /// While that wouldn't lead to UB it goes against the purpose of this library 163 - fn get_data_mut(&mut self) -> &mut T { 164 - // SAFETY: When creating the writeguad it is checked that the reader doesnt have access to the same data 165 - // This function requires &mut self so there also isn't any ref created by writeguard. 166 - // SAFETY: the ptr is never null, therefore unwrap_unchecked 110 + impl<T> Drop for Reader<T> { 111 + fn drop(&mut self) { 112 + // SAFETY: Shared.should_drop() is called. on true object really is dropped. on false it isnt. 113 + // This is the last use of self and therefore also of Shared 167 114 unsafe { 168 - self.writer 169 - .shared 170 - .get_value(self.writer.write_ptr) 171 - .get() 172 - .as_mut() 173 - .unwrap_unchecked() 115 + let should_drop = self.shared_ref().should_drop(); 116 + if should_drop { 117 + _ = Box::from_raw(self.shared.as_ptr()); 118 + } 174 119 } 175 120 } 176 121 } 177 122 178 - impl<'a, T: Absorb<O>, O> WriteGuard<'a, T, O> { 179 - /// created a new `WriteGuard` and syncs the two values if needed. 180 - /// 181 - /// ### SAFETY 182 - /// No `ReadGuard` is allowed to exist to the same value the `Writer.write_ptr` points to 183 - /// 184 - /// Assuming a correct `Reader` & `ReadGuard` implementation: 185 - /// If Inner.read_state.can_write(Writer.write_ptr) == true this function is fine to call 186 - unsafe fn new(writer: &'a mut Writer<T, O>) -> Self { 187 - let mut guard = Self { writer }; 188 - while let Some(operation) = guard.writer.op_buffer.pop_front() { 189 - guard.get_data_mut().absorb(operation); 190 - } 191 - guard 123 + /// Data won't change while holding the Guard. This also means the Writer can only issue one swap, while Guard is being held 124 + /// If T: !Sync this is guaranteed to be the only ref to this T 125 + /// 126 + /// Doesn't implement Clone as that would require refcounting to know when to unlock. 127 + #[derive(Debug)] 128 + pub struct ReadGuard<'a, T> { 129 + data: &'a T, 130 + state: &'a AtomicU8, 131 + /// PhantomData makes the borrow checker prove that there only ever is one ReadGuard. 132 + /// This allows resetting the readstate without some kind of counter 133 + reader: PhantomData<&'a mut Reader<T>>, 134 + } 135 + 136 + impl<'a, T> Deref for ReadGuard<'a, T> { 137 + type Target = T; 138 + 139 + fn deref(&self) -> &Self::Target { 140 + self.data 192 141 } 193 142 } 194 143 195 - impl<T: Absorb<O>, O: Clone> WriteGuard<'_, T, O> { 196 - /// applies operation to the current write Value and stores it to apply to the other later. 197 - /// If there is no reader the operation is applied to both values immediately and not stored. 198 - pub fn apply_op(&mut self, operation: O) { 199 - if let Some(inner) = Arc::get_mut(&mut self.writer.shared) { 200 - inner.value_1.get_mut().absorb(operation.clone()); 201 - inner.value_2.get_mut().absorb(operation); 202 - } else { 203 - self.writer.op_buffer.push_back(operation.clone()); 204 - self.get_data_mut().absorb(operation); 205 - } 144 + impl<T, E> AsRef<E> for ReadGuard<'_, T> 145 + where 146 + E: ?Sized, 147 + T: AsRef<E>, 148 + { 149 + fn as_ref(&self) -> &E { 150 + self.deref().as_ref() 206 151 } 207 152 } 208 153 209 - impl<T, O> Drop for WriteGuard<'_, T, O> { 154 + /// SAFETY: behaves like a ref to T. https://doc.rust-lang.org/std/marker/trait.Sync.html 155 + unsafe impl<T: Sync> Send for ReadGuard<'_, T> {} 156 + /// SAFETY: behaves like a ref to T. https://doc.rust-lang.org/std/marker/trait.Sync.html 157 + unsafe impl<T: Sync> Sync for ReadGuard<'_, T> {} 158 + 159 + impl<T> Drop for ReadGuard<'_, T> { 210 160 fn drop(&mut self) { 211 - self.writer.swap(); 161 + // release the read lock 162 + self.state.fetch_and(0b100, Ordering::Release); 212 163 } 213 164 } 214 165 215 - /// Not realtime safe Object which can change the internal T value 166 + /// Not realtime safe object which can change the internal T value. 216 167 #[derive(Debug)] 217 168 pub struct Writer<T, O> { 218 - shared: Arc<Shared<T>>, 169 + shared: NonNull<Shared<T>>, 219 170 // sets which buffer the next write is applied to 220 171 // write_ptr doesn't need to be Atomics as it only changes, when the Writer itself swaps 221 172 write_ptr: Ptr, 222 173 // buffer is pushed at the back and popped at the front. 223 174 op_buffer: VecDeque<O>, 175 + // needed for drop_check 176 + _own: PhantomData<Shared<T>>, 224 177 } 225 178 226 179 impl<T, O> Writer<T, O> { 180 + const fn shared_ref(&self) -> &Shared<T> { 181 + // SAFETY: Reader always has a valid Shared<T>, a mut ref to a shared is never created, 182 + // only to the UnsafeCell<T>s inside of it 183 + unsafe { self.shared.as_ref() } 184 + } 185 + 227 186 /// swaps the read and write values. If no changes were made since the last swap nothing happens. Never blocks 228 - /// not public as swapping without creating a `WriteGuard` is pretty 187 + /// not public as swapping without creating a before `WriteGuard` is pretty useless 229 188 fn swap(&mut self) { 230 189 if self.op_buffer.is_empty() { 231 190 return; 232 191 } 233 192 234 193 match self.write_ptr { 235 - Ptr::Value1 => self.shared.state.fetch_and(0b011, Ordering::Release), 236 - Ptr::Value2 => self.shared.state.fetch_or(0b100, Ordering::Release), 194 + Ptr::Value1 => self.shared_ref().state.fetch_and(0b011, Ordering::Release), 195 + Ptr::Value2 => self.shared_ref().state.fetch_or(0b100, Ordering::Release), 237 196 }; 238 197 239 198 self.write_ptr.switch(); ··· 241 200 242 201 /// get a Reader if none exists 243 202 pub fn build_reader(&mut self) -> Option<Reader<T>> { 244 - if Arc::get_mut(&mut self.shared).is_some() { 245 - Some(Reader { 246 - inner: self.shared.clone(), 247 - }) 248 - } else { 249 - None 250 - } 251 - } 252 - 253 - /// The Value returned may be newer than the version the reader is currently seeing. 254 - /// This value will be written to next. 255 - #[must_use] 256 - pub fn read(&self) -> &T { 257 - // SAFETY: Only the WriteGuard can write to the values / create mut refs to them. 258 - // The WriteGuard holds a mut ref to the writer so this function can't be called while a writeguard exists 259 - // This means that reading them / creating refs is safe to do 203 + // SAFETY: all is_unique_with_increase requirements are satisfied. 260 204 unsafe { 261 - self.shared 262 - .get_value(self.write_ptr) 263 - .get() 264 - .as_ref() 265 - .unwrap_unchecked() 205 + if self.shared_ref().is_unique_with_increase() { 206 + Some(Reader { 207 + shared: self.shared, 208 + _own: PhantomData, 209 + }) 210 + } else { 211 + None 212 + } 266 213 } 267 214 } 268 215 } ··· 276 223 277 224 loop { 278 225 // operation has to be aquire, but only the time it breaks the loop 279 - let state = self.shared.state.load(Ordering::Relaxed); 226 + let state = self.shared_ref().state.load(Ordering::Relaxed); 280 227 281 228 // SAFETY: is in state internal only value which is only set by library code 282 229 let state = unsafe { ReadState::from_u8_ignore_ptr(state) }; ··· 306 253 307 254 loop { 308 255 // operation has to be aquire, but only the time it breaks the loop 309 - let state = self.shared.state.load(Ordering::Relaxed); 256 + let state = self.shared_ref().state.load(Ordering::Relaxed); 310 257 311 258 // SAFETY: is in state internal only value which is only set by library code 312 259 let state = unsafe { ReadState::from_u8_ignore_ptr(state) }; ··· 338 285 339 286 loop { 340 287 // operation has to be aquire, but only the time it breaks the loop 341 - let state = self.shared.state.load(Ordering::Relaxed); 288 + let state = self.shared_ref().state.load(Ordering::Relaxed); 342 289 343 290 // SAFETY: is in state internal only value which is only set by library code 344 291 let state = unsafe { ReadState::from_u8_ignore_ptr(state) }; ··· 365 312 366 313 /// doesn't block. Returns None if the Reader has a `ReadGuard` pointing to the old value 367 314 pub fn try_lock(&mut self) -> Option<WriteGuard<'_, T, O>> { 368 - let state = self.shared.state.load(Ordering::Acquire); 315 + let state = self.shared_ref().state.load(Ordering::Acquire); 369 316 370 317 // SAFETY: is in state internal only value which is only set by library code 371 318 let state = unsafe { ReadState::from_u8_ignore_ptr(state) }; ··· 382 329 impl<T: Clone, O> Writer<T, O> { 383 330 /// Creates a new Writer by cloning the value once to get two values 384 331 pub fn new(value: T) -> Self { 385 - let mut shared: Arc<MaybeUninit<Shared<T>>> = Arc::new_uninit(); 332 + // SAFETY: ptr was just alloced, so is valid and unique. 333 + let mut shared: Box<MaybeUninit<Shared<T>>> = Box::new_uninit(); 334 + Shared::initialize_state(&mut shared); 335 + let shared_ptr = shared.as_mut_ptr(); 386 336 387 - // SAFETY: Arc was just created, therefore no one has acces to it. 388 - // Every field gets initialized 337 + // SAFETY: Every field gets initialized, ptr is valid and doesn't alias 389 338 let shared = unsafe { 390 - let shared_ptr = Arc::get_mut(&mut shared).unwrap_unchecked().as_mut_ptr(); 391 - (&raw mut (*shared_ptr).state).write(AtomicU8::new(0b000)); 392 339 UnsafeCell::raw_get(&raw const (*shared_ptr).value_1).write(value.clone()); 393 - UnsafeCell::raw_get(&raw const (*shared_ptr).value_1).write(value); 394 - shared.assume_init() 340 + UnsafeCell::raw_get(&raw const (*shared_ptr).value_2).write(value); 341 + // consumes the Box<MaybeUninit> and creates the NonNull with an initialized value 342 + NonNull::new_unchecked(Box::into_raw(shared.assume_init())) 395 343 }; 396 344 397 345 Writer { 398 346 shared, 399 347 write_ptr: Ptr::Value2, 400 348 op_buffer: VecDeque::new(), 349 + _own: PhantomData, 401 350 } 402 351 } 403 352 } ··· 409 358 /// 410 359 /// Could leak a T object if T::default() panics. 411 360 fn default() -> Self { 412 - let mut shared: Arc<MaybeUninit<Shared<T>>> = Arc::new_uninit(); 361 + // SAFETY: ptr was just alloced, so is valid and unique. 362 + let mut shared: Box<MaybeUninit<Shared<T>>> = Box::new_uninit(); 363 + Shared::initialize_state(&mut shared); 364 + let shared_ptr = shared.as_mut_ptr(); 413 365 414 - // SAFETY: Arc was just created, therefore no one has acces to it. 415 - // Every field gets initialized 366 + // SAFETY: Every field gets initialized, ptr is valid and doesn't alias 416 367 let shared = unsafe { 417 - let shared_ptr = Arc::get_mut(&mut shared).unwrap_unchecked().as_mut_ptr(); 418 - (&raw mut (*shared_ptr).state).write(AtomicU8::new(0b000)); 419 368 UnsafeCell::raw_get(&raw const (*shared_ptr).value_1).write(T::default()); 420 - UnsafeCell::raw_get(&raw const (*shared_ptr).value_1).write(T::default()); 421 - shared.assume_init() 369 + UnsafeCell::raw_get(&raw const (*shared_ptr).value_2).write(T::default()); 370 + // consumes the Box<MaybeUninit> and creates the NonNull with an initialized value 371 + NonNull::new_unchecked(Box::into_raw(shared.assume_init())) 422 372 }; 423 373 424 374 Writer { 425 375 shared, 426 376 write_ptr: Ptr::Value2, 427 377 op_buffer: VecDeque::new(), 378 + _own: PhantomData, 428 379 } 429 380 } 430 381 } 382 + 383 + impl<T: Sync, O> Writer<T, O> { 384 + /// The Value returned may be newer than the version the reader is currently seeing. 385 + /// This value will be written to next. 386 + /// 387 + /// Needs T: Sync because maybe this is the value the reader is curently reading 388 + pub fn read(&self) -> &T { 389 + // SAFETY: Only the WriteGuard can write to the values / create mut refs to them. 390 + // The WriteGuard holds a mut ref to the writer so this function can't be called while a writeguard exists 391 + // This means that reading them / creating refs is safe to do 392 + unsafe { 393 + self.shared_ref() 394 + .get_value(self.write_ptr) 395 + .get() 396 + .as_ref() 397 + .unwrap_unchecked() 398 + } 399 + } 400 + } 401 + 402 + /// SAFETY: owns T and O 403 + unsafe impl<T: Send, O: Send> Send for Writer<T, O> {} 404 + /// SAFETY: &self fn can only create a &T and doesn't allow access to O 405 + unsafe impl<T: Sync, O> Sync for Writer<T, O> {} 406 + 407 + impl<T, O> Drop for Writer<T, O> { 408 + fn drop(&mut self) { 409 + // SAFETY: Shared.should_drop() is called. on true object really is dropped. on false it isnt. 410 + // This is the last use of self and therefore also of Shared 411 + unsafe { 412 + let should_drop = self.shared_ref().should_drop(); 413 + if should_drop { 414 + _ = Box::from_raw(self.shared.as_ptr()); 415 + } 416 + } 417 + } 418 + } 419 + 420 + // Don't create a WriteGuard directly, as that wouldn't sync with old Operations 421 + /// Can be used to write to the Data structure. 422 + /// 423 + /// When this structure exists the Reader already switched to the other value 424 + /// 425 + /// Dropping this makes all changes available to the Reader. 426 + #[derive(Debug)] 427 + pub struct WriteGuard<'a, T, O> { 428 + writer: &'a mut Writer<T, O>, 429 + } 430 + 431 + impl<T, O> WriteGuard<'_, T, O> { 432 + /// Makes the changes available to the reader. Equivalent to std::mem::drop(self) 433 + pub fn swap(self) {} 434 + 435 + /// Gets the value currently being written to. 436 + pub fn read(&self) -> &T { 437 + // SAFETY: Only the WriteGuard can write to the values / create mut refs to them. 438 + // The WriteGuard holds a mut ref to the writer so this function can't be called while a writeguard exists 439 + // This means that reading them / creating refs is safe to do 440 + unsafe { 441 + self.writer.shared_ref() 442 + .get_value(self.writer.write_ptr) 443 + .get() 444 + .as_ref() 445 + .unwrap_unchecked() 446 + } 447 + } 448 + 449 + /// Isn't public as this could easily create disconnects between the two versions. 450 + /// While that wouldn't lead to UB it goes against the purpose of this library 451 + fn get_data_mut(&mut self) -> &mut T { 452 + // SAFETY: When creating the writeguad it is checked that the reader doesnt have access to the same data 453 + // This function requires &mut self so there also isn't any ref created by writeguard. 454 + // SAFETY: the ptr is never null, therefore unwrap_unchecked 455 + unsafe { 456 + self.writer 457 + .shared_ref() 458 + .get_value(self.writer.write_ptr) 459 + .get() 460 + .as_mut() 461 + .unwrap_unchecked() 462 + } 463 + } 464 + } 465 + 466 + impl<'a, T: Absorb<O>, O> WriteGuard<'a, T, O> { 467 + /// created a new `WriteGuard` and syncs the two values if needed. 468 + /// 469 + /// ### SAFETY 470 + /// No `ReadGuard` is allowed to exist to the same value the `Writer.write_ptr` points to 471 + /// 472 + /// Assuming a correct `Reader` & `ReadGuard` implementation: 473 + /// If Inner.read_state.can_write(Writer.write_ptr) == true this function is fine to call 474 + unsafe fn new(writer: &'a mut Writer<T, O>) -> Self { 475 + let mut guard = Self { writer }; 476 + while let Some(operation) = guard.writer.op_buffer.pop_front() { 477 + guard.get_data_mut().absorb(operation); 478 + } 479 + guard 480 + } 481 + } 482 + 483 + impl<T: Absorb<O>, O: Clone> WriteGuard<'_, T, O> { 484 + /// applies operation to the current write Value and stores it to apply to the other later. 485 + /// If there is no reader the operation is applied to both values immediately and not stored. 486 + pub fn apply_op(&mut self, operation: O) { 487 + if self.writer.shared_ref().is_unique() { 488 + let shared_ref = self.writer.shared_ref(); 489 + // SAFETY: is_unique checked that no Reader exists. I am the only one with access to Shared<T>, so i can modify whatever i want. 490 + unsafe { 491 + (*shared_ref.value_1.get()).absorb(operation.clone()); 492 + (*shared_ref.value_2.get()).absorb(operation); 493 + } 494 + } else { 495 + self.writer.op_buffer.push_back(operation.clone()); 496 + self.get_data_mut().absorb(operation); 497 + } 498 + } 499 + } 500 + 501 + /// SAFETY: behaves like a &mut T and &mut Vec<O>. https://doc.rust-lang.org/stable/std/marker/trait.Sync.html 502 + unsafe impl<T: Send, O: Send> Send for WriteGuard<'_, T, O> {} 503 + 504 + /// Safety: can only create shared refs to T, not to O. https://doc.rust-lang.org/stable/std/marker/trait.Sync.html 505 + unsafe impl<T: Sync, O> Sync for WriteGuard<'_, T, O> {} 506 + 507 + impl<T, O> Drop for WriteGuard<'_, T, O> { 508 + fn drop(&mut self) { 509 + self.writer.swap(); 510 + } 511 + }