#![cfg_attr(not(feature = "ref-counting"), allow(dead_code))]
use std::{ops::Deref, sync::atomic::{AtomicUsize, Ordering}};
pub struct AtomicLendCell<T> {
data: T,
refcount: AtomicUsize
}
impl<T> AtomicLendCell<T> {
pub fn as_ref(&self) -> &T{
&self.data
}
}
impl<T> Deref for AtomicLendCell<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.as_ref()
}
}
impl<T> Drop for AtomicLendCell<T> {
fn drop(&mut self) {
if self.refcount.load(Ordering::Relaxed) > 0 {
panic!("An AtomicBorrowCell outlives the AtomicLendCell which issues it!");
}
}
}
pub struct AtomicBorrowCell<T> {
data_ptr: *const T,
refcount_ptr: *const AtomicUsize
}
impl<T> AtomicBorrowCell<T> {
pub fn as_ref(&self) -> &T{
unsafe {self.data_ptr.as_ref().unwrap()}
}
}
impl<T> Deref for AtomicBorrowCell<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.as_ref()
}
}
impl<T> Drop for AtomicBorrowCell<T> {
fn drop(&mut self) {
unsafe {
self.refcount_ptr.as_ref().unwrap().fetch_sub(1, Ordering::Release);
}
}
}
unsafe impl<T: Sync> Send for AtomicBorrowCell<T> {}
unsafe impl<T: Sync> Sync for AtomicBorrowCell<T> {}
impl<T> AtomicLendCell<T> {
pub fn new(data: T) -> Self {
Self {data, refcount: 0.into()}
}
pub fn borrow(&self) -> AtomicBorrowCell<T> {
self.refcount.fetch_add(1, Ordering::Acquire);
AtomicBorrowCell {data_ptr: (&self.data) as * const T, refcount_ptr: &self.refcount as * const AtomicUsize}
}
}
impl<'a, T> AtomicLendCell<&'a T> {
pub fn borrow_deref(&'a self) -> AtomicBorrowCell<T> {
self.refcount.fetch_add(1, Ordering::Acquire);
AtomicBorrowCell {data_ptr: self.data as * const T, refcount_ptr: &self.refcount as * const AtomicUsize}
}
}
impl<T> Clone for AtomicBorrowCell<T> {
fn clone(&self) -> Self {
let count = unsafe {self.refcount_ptr.as_ref()}.unwrap();
count.fetch_add(1, Ordering::SeqCst);
AtomicBorrowCell {data_ptr: self.data_ptr, refcount_ptr: self.refcount_ptr}
}
}
#[test]
fn test_lambda_borrow(){
let x = AtomicLendCell::new(4);
let xr = x.borrow();
let t1 = std::thread::spawn(move ||{
let y = xr.as_ref();
println!("{:?}", y);
});
let xr = x.borrow();
let t2 = std::thread::spawn(move ||{
let y = xr.as_ref();
println!("{:?}", y);
});
t1.join().unwrap();
t2.join().unwrap();
}