aboutsummaryrefslogtreecommitdiffstats
path: root/nihav-core/src/refs.rs
diff options
context:
space:
mode:
authorKostya Shishkov <kostya.shishkov@gmail.com>2019-04-28 15:15:50 +0200
committerKostya Shishkov <kostya.shishkov@gmail.com>2019-04-28 15:15:50 +0200
commit1a967e6bad5f17943b4de0607078eb940ad5adfe (patch)
treef4f88a32dbe9c42d736130b493bc5a7ce308d20e /nihav-core/src/refs.rs
parent3c38de0f394218a267cf15edda331dc4f2ed61bb (diff)
downloadnihav-1a967e6bad5f17943b4de0607078eb940ad5adfe.tar.gz
switch to refcounted buffers
Diffstat (limited to 'nihav-core/src/refs.rs')
-rw-r--r--nihav-core/src/refs.rs87
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());
+ }
+ }
+}
+