core/frame: add get_num_components() call to NAVideoBuffer
[nihav.git] / nihav-core / src / refs.rs
1 use std::ops::{Deref, DerefMut};
2 use std::convert::AsRef;
3 use std::sync::atomic::*;
4
5 struct NABufferData<T> {
6 data: T,
7 refs: AtomicUsize,
8 }
9
10 impl<T> NABufferData<T> {
11 fn new(data: T) -> Self {
12 Self {
13 data,
14 refs: AtomicUsize::new(1),
15 }
16 }
17 fn inc_refs(obj: &mut Self) {
18 obj.refs.fetch_add(1, Ordering::SeqCst);
19 }
20 fn dec_refs(obj: &mut Self) -> bool {
21 obj.refs.fetch_sub(1, Ordering::SeqCst) == 1
22 }
23 fn get_num_refs(obj: &Self) -> usize {
24 obj.refs.load(Ordering::Relaxed)
25 }
26 fn get_read_ptr(obj: &Self) -> &T {
27 &obj.data
28 }
29 fn get_write_ptr(obj: &mut Self) -> Option<&mut T> {
30 Some(&mut obj.data)
31 }
32 }
33
34 pub struct NABufferRef<T> {
35 ptr: *mut NABufferData<T>,
36 }
37
38 unsafe impl<T> Sync for NABufferRef<T> {}
39 unsafe impl<T> Send for NABufferRef<T> {}
40
41 impl<T> NABufferRef<T> {
42 pub fn new(val: T) -> Self {
43 let bdata = NABufferData::new(val);
44 let nbox: Box<_> = Box::new(bdata);
45 Self { ptr: Box::into_raw(nbox) }
46 }
47 pub fn get_num_refs(&self) -> usize {
48 unsafe {
49 NABufferData::get_num_refs(self.ptr.as_mut().unwrap())
50 }
51 }
52 pub fn as_mut(&mut self) -> Option<&mut T> {
53 unsafe {
54 NABufferData::get_write_ptr(self.ptr.as_mut().unwrap())
55 }
56 }
57 }
58
59 impl<T> AsRef<T> for NABufferRef<T> {
60 fn as_ref(&self) -> &T {
61 unsafe {
62 NABufferData::get_read_ptr(self.ptr.as_mut().unwrap())
63 }
64 }
65 }
66
67 impl<T> Deref for NABufferRef<T> {
68 type Target = T;
69 fn deref(&self) -> &T { self.as_ref() }
70 }
71
72 impl<T> DerefMut for NABufferRef<T> {
73 fn deref_mut(&mut self) -> &mut T { self.as_mut().unwrap() }
74 }
75
76 impl<T> Clone for NABufferRef<T> {
77 fn clone(&self) -> Self {
78 unsafe {
79 NABufferData::inc_refs(self.ptr.as_mut().unwrap());
80 }
81 Self { ptr: self.ptr }
82 }
83 }
84
85 impl<T> Drop for NABufferRef<T> {
86 fn drop(&mut self) {
87 unsafe {
88 if NABufferData::dec_refs(self.ptr.as_mut().unwrap()) {
89 let data = Box::from_raw(self.ptr);
90 std::mem::drop(data);
91 }
92 }
93 }
94 }
95
96 impl<T:Default> Default for NABufferRef<T> {
97 fn default() -> Self {
98 Self::new(T::default())
99 }
100 }