diff options
author | Kostya Shishkov <kostya.shishkov@gmail.com> | 2019-04-28 15:15:50 +0200 |
---|---|---|
committer | Kostya Shishkov <kostya.shishkov@gmail.com> | 2019-04-28 15:15:50 +0200 |
commit | 1a967e6bad5f17943b4de0607078eb940ad5adfe (patch) | |
tree | f4f88a32dbe9c42d736130b493bc5a7ce308d20e /nihav-core/src/refs.rs | |
parent | 3c38de0f394218a267cf15edda331dc4f2ed61bb (diff) | |
download | nihav-1a967e6bad5f17943b4de0607078eb940ad5adfe.tar.gz |
switch to refcounted buffers
Diffstat (limited to 'nihav-core/src/refs.rs')
-rw-r--r-- | nihav-core/src/refs.rs | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/nihav-core/src/refs.rs b/nihav-core/src/refs.rs new file mode 100644 index 0000000..f2b0577 --- /dev/null +++ b/nihav-core/src/refs.rs @@ -0,0 +1,87 @@ +use std::ops::{Deref, DerefMut}; +use std::sync::atomic::*; + +struct NABufferData<T> { + data: T, + refs: AtomicUsize, +} + +impl<T> NABufferData<T> { + fn new(data: T) -> Self { + Self { + data: data, + refs: AtomicUsize::new(1), + } + } + fn inc_refs(obj: &mut Self) { + obj.refs.fetch_add(1, Ordering::SeqCst); + } + fn dec_refs(obj: &mut Self) { + if obj.refs.fetch_sub(1, Ordering::SeqCst) == 0 { + std::mem::forget(obj); + } + } + fn get_num_refs(obj: &Self) -> usize { + obj.refs.load(Ordering::Relaxed) + } + fn get_read_ptr(obj: &Self) -> &T { + &obj.data + } + fn get_write_ptr(obj: &mut Self) -> Option<&mut T> { + Some(&mut obj.data) + } +} + +pub struct NABufferRef<T> { + ptr: *mut NABufferData<T>, +} + +impl<T> NABufferRef<T> { + pub fn new(val: T) -> Self { + let bdata = NABufferData::new(val); + let nbox: Box<_> = Box::new(bdata); + Self { ptr: Box::into_raw(nbox) } + } + pub fn get_num_refs(&self) -> usize { + unsafe { + NABufferData::get_num_refs(self.ptr.as_mut().unwrap()) + } + } + pub fn as_ref(&self) -> &T { + unsafe { + NABufferData::get_read_ptr(self.ptr.as_mut().unwrap()) + } + } + pub fn as_mut(&mut self) -> Option<&mut T> { + unsafe { + NABufferData::get_write_ptr(self.ptr.as_mut().unwrap()) + } + } +} + +impl<T> Deref for NABufferRef<T> { + type Target = T; + fn deref(&self) -> &T { self.as_ref() } +} + +impl<T> DerefMut for NABufferRef<T> { + fn deref_mut(&mut self) -> &mut T { self.as_mut().unwrap() } +} + +impl<T> Clone for NABufferRef<T> { + fn clone(&self) -> Self { + unsafe { + NABufferData::inc_refs(self.ptr.as_mut().unwrap()); + } + Self { ptr: self.ptr } + } +} + +impl<T> Drop for NABufferRef<T> { + fn drop(&mut self) { + unsafe { + NABufferData::dec_refs(self.ptr.as_mut().unwrap()); + } + } +} + |