use std::rc::Rc;
use std::sync::{Arc, mpsc};
pub trait Handle: Clone {
#[inline]
#[must_use = "creating a handle without using it has no effect"]
fn handle(&self) -> Self {
self.clone()
}
}
impl<T: ?Sized> Handle for &T {}
impl<T: ?Sized> Handle for Rc<T> {}
impl<T: ?Sized> Handle for Arc<T> {}
impl<T> Handle for mpsc::Sender<T> {}
impl<T> Handle for mpsc::SyncSender<T> {}
#[cfg(test)]
mod tests {
use super::*;
use std::cell::RefCell;
use std::sync::atomic::{AtomicU32, Ordering};
#[test]
fn test_shared_reference_handle() {
let value = 42;
let ref1 = &value;
let ref2 = ref1.handle();
assert_eq!(*ref1, *ref2);
assert_eq!(*ref1, 42);
}
#[test]
fn test_rc_handle_entanglement() {
let data = Rc::new(RefCell::new(vec![1, 2, 3]));
let handle1 = data.handle();
let handle2 = data.handle();
assert_eq!(Rc::strong_count(&data), 3);
data.borrow_mut().push(4);
assert_eq!(*handle1.borrow(), vec![1, 2, 3, 4]);
assert_eq!(*handle2.borrow(), vec![1, 2, 3, 4]);
}
#[test]
fn test_arc_handle_entanglement() {
let counter = Arc::new(AtomicU32::new(0));
let handle1 = counter.handle();
let handle2 = counter.handle();
assert_eq!(Arc::strong_count(&counter), 3);
counter.fetch_add(1, Ordering::SeqCst);
handle1.fetch_add(1, Ordering::SeqCst);
handle2.fetch_add(1, Ordering::SeqCst);
assert_eq!(counter.load(Ordering::SeqCst), 3);
assert_eq!(handle1.load(Ordering::SeqCst), 3);
assert_eq!(handle2.load(Ordering::SeqCst), 3);
}
#[test]
fn test_mpsc_sender_handle() {
let (tx, rx) = mpsc::channel();
let tx_handle = tx.handle();
tx.send(1).unwrap();
tx_handle.send(2).unwrap();
assert_eq!(rx.recv().unwrap(), 1);
assert_eq!(rx.recv().unwrap(), 2);
}
#[test]
fn test_handle_is_clone() {
let rc = Rc::new(42);
let via_handle = rc.handle();
let via_clone = rc.clone();
assert_eq!(*via_handle, *via_clone);
assert_eq!(Rc::strong_count(&rc), 3);
}
}