]> git.nihav.org Git - nihav.git/blobdiff - nihav-core/src/refs.rs
core/refs: fix leak
[nihav.git] / nihav-core / src / refs.rs
index b83aa25428b7c75df67182efa73536a646fb7d7d..4c2e2903a0f3e11b4a02a093f93d158398ff6656 100644 (file)
@@ -1,4 +1,5 @@
 use std::ops::{Deref, DerefMut};
+use std::convert::AsRef;
 use std::sync::atomic::*;
 
 struct NABufferData<T> {
@@ -9,17 +10,15 @@ struct NABufferData<T> {
 impl<T> NABufferData<T> {
     fn new(data: T) -> Self {
         Self {
-            data:       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 dec_refs(obj: &mut Self) -> bool {
+        obj.refs.fetch_sub(1, Ordering::SeqCst) == 1
     }
     fn get_num_refs(obj: &Self) -> usize {
         obj.refs.load(Ordering::Relaxed)
@@ -47,14 +46,17 @@ impl<T> NABufferRef<T> {
             NABufferData::get_num_refs(self.ptr.as_mut().unwrap())
         }
     }
-    pub fn as_ref(&self) -> &T {
+    pub fn as_mut(&mut self) -> Option<&mut T> {
         unsafe {
-            NABufferData::get_read_ptr(self.ptr.as_mut().unwrap())
+            NABufferData::get_write_ptr(self.ptr.as_mut().unwrap())
         }
     }
-    pub fn as_mut(&mut self) -> Option<&mut T> {
+}
+
+impl<T> AsRef<T> for NABufferRef<T> {
+    fn as_ref(&self) -> &T {
         unsafe {
-            NABufferData::get_write_ptr(self.ptr.as_mut().unwrap())
+            NABufferData::get_read_ptr(self.ptr.as_mut().unwrap())
         }
     }
 }
@@ -80,7 +82,10 @@ impl<T> Clone for NABufferRef<T> {
 impl<T> Drop for NABufferRef<T> {
     fn drop(&mut self) {
         unsafe {
-            NABufferData::dec_refs(self.ptr.as_mut().unwrap());
+            if NABufferData::dec_refs(self.ptr.as_mut().unwrap()) {
+                let data = Box::from_raw(self.ptr);
+                std::mem::drop(data);
+            }
         }
     }
 }