| 1 | //! Reference-counted buffer data type. |
| 2 | //! |
| 3 | //! NihAV requires some reference-counted type especially for frame buffer pools. |
| 4 | //! `Arc` does not allow mutability with several references present, `RwLock` does not work reliably in a single thread mode (at least for me) so I ended up NIHing something. |
| 5 | //! |
| 6 | //! Currently it does not prevent code from reading the data that is being written to. |
| 7 | //! Maybe in the future this will be replaced by something better and using more standard components. |
| 8 | //! |
| 9 | //! Also it contains `unsafe{}` so I should not write in Rust at all. |
| 10 | //! |
| 11 | //! # Examples |
| 12 | //! |
| 13 | //! ``` |
| 14 | //! use nihav_core::refs::NABufferRef; |
| 15 | //! |
| 16 | //! let vec = vec![42u8; 16]; |
| 17 | //! let vec_ref = NABufferRef::new(vec); |
| 18 | //! let vec_ref2 = vec_ref.clone(); |
| 19 | //! let ref_count = vec_ref.get_num_refs(); // should be 2 |
| 20 | //! println!("vector element 4 is {}", vec_ref[4]); // should print the fourth vector element |
| 21 | //! ``` |
| 22 | use std::ops::{Deref, DerefMut}; |
| 23 | use std::convert::AsRef; |
| 24 | use std::sync::atomic::*; |
| 25 | |
| 26 | struct NABufferData<T> { |
| 27 | data: T, |
| 28 | refs: AtomicUsize, |
| 29 | } |
| 30 | |
| 31 | impl<T> NABufferData<T> { |
| 32 | fn new(data: T) -> Self { |
| 33 | Self { |
| 34 | data, |
| 35 | refs: AtomicUsize::new(1), |
| 36 | } |
| 37 | } |
| 38 | fn inc_refs(obj: &mut Self) { |
| 39 | obj.refs.fetch_add(1, Ordering::SeqCst); |
| 40 | } |
| 41 | fn dec_refs(obj: &mut Self) -> bool { |
| 42 | obj.refs.fetch_sub(1, Ordering::SeqCst) == 1 |
| 43 | } |
| 44 | fn get_num_refs(obj: &Self) -> usize { |
| 45 | obj.refs.load(Ordering::Relaxed) |
| 46 | } |
| 47 | fn get_read_ptr(obj: &Self) -> &T { |
| 48 | &obj.data |
| 49 | } |
| 50 | fn get_write_ptr(obj: &mut Self) -> Option<&mut T> { |
| 51 | Some(&mut obj.data) |
| 52 | } |
| 53 | } |
| 54 | |
| 55 | /// Reference-counted buffer reference. |
| 56 | pub struct NABufferRef<T> { |
| 57 | ptr: *mut NABufferData<T>, |
| 58 | } |
| 59 | |
| 60 | unsafe impl<T> Sync for NABufferRef<T> {} |
| 61 | unsafe impl<T> Send for NABufferRef<T> {} |
| 62 | |
| 63 | impl<T> NABufferRef<T> { |
| 64 | /// Constructs a new instance of `NABufferRef`. |
| 65 | pub fn new(val: T) -> Self { |
| 66 | let bdata = NABufferData::new(val); |
| 67 | let nbox: Box<_> = Box::new(bdata); |
| 68 | Self { ptr: Box::into_raw(nbox) } |
| 69 | } |
| 70 | /// Reports the number of references for the current instance. |
| 71 | pub fn get_num_refs(&self) -> usize { |
| 72 | unsafe { |
| 73 | NABufferData::get_num_refs(self.ptr.as_mut().unwrap()) |
| 74 | } |
| 75 | } |
| 76 | /// Returns a mutable pointer to the underlying data if possible. |
| 77 | pub fn as_mut(&mut self) -> Option<&mut T> { |
| 78 | unsafe { |
| 79 | NABufferData::get_write_ptr(self.ptr.as_mut().unwrap()) |
| 80 | } |
| 81 | } |
| 82 | } |
| 83 | |
| 84 | impl<T> AsRef<T> for NABufferRef<T> { |
| 85 | fn as_ref(&self) -> &T { |
| 86 | unsafe { |
| 87 | NABufferData::get_read_ptr(self.ptr.as_mut().unwrap()) |
| 88 | } |
| 89 | } |
| 90 | } |
| 91 | |
| 92 | impl<T> Deref for NABufferRef<T> { |
| 93 | type Target = T; |
| 94 | fn deref(&self) -> &T { self.as_ref() } |
| 95 | } |
| 96 | |
| 97 | impl<T> DerefMut for NABufferRef<T> { |
| 98 | fn deref_mut(&mut self) -> &mut T { self.as_mut().unwrap() } |
| 99 | } |
| 100 | |
| 101 | impl<T> Clone for NABufferRef<T> { |
| 102 | fn clone(&self) -> Self { |
| 103 | unsafe { |
| 104 | NABufferData::inc_refs(self.ptr.as_mut().unwrap()); |
| 105 | } |
| 106 | Self { ptr: self.ptr } |
| 107 | } |
| 108 | } |
| 109 | |
| 110 | impl<T> Drop for NABufferRef<T> { |
| 111 | fn drop(&mut self) { |
| 112 | unsafe { |
| 113 | if NABufferData::dec_refs(self.ptr.as_mut().unwrap()) { |
| 114 | let data = Box::from_raw(self.ptr); |
| 115 | std::mem::drop(data); |
| 116 | } |
| 117 | } |
| 118 | } |
| 119 | } |
| 120 | |
| 121 | impl<T:Default> Default for NABufferRef<T> { |
| 122 | fn default() -> Self { |
| 123 | Self::new(T::default()) |
| 124 | } |
| 125 | } |