oxihuman_core/
weak_reference.rs1#![allow(dead_code)]
4
5use std::cell::Cell;
10use std::rc::Rc;
11
12struct Token {
14 alive: Cell<bool>,
15}
16
17pub struct StrongOwner<T> {
19 value: T,
20 token: Rc<Token>,
21}
22
23impl<T> StrongOwner<T> {
24 pub fn new(value: T) -> (Self, WeakRef<T>) {
26 let token = Rc::new(Token {
27 alive: Cell::new(true),
28 });
29 let weak = WeakRef {
30 token: Rc::clone(&token),
31 _marker: std::marker::PhantomData,
32 };
33 (Self { value, token }, weak)
34 }
35
36 pub fn get(&self) -> &T {
38 &self.value
39 }
40}
41
42impl<T> Drop for StrongOwner<T> {
43 fn drop(&mut self) {
44 self.token.alive.set(false);
45 }
46}
47
48pub struct WeakRef<T> {
50 token: Rc<Token>,
51 _marker: std::marker::PhantomData<*const T>,
52}
53
54impl<T> WeakRef<T> {
55 pub fn is_alive(&self) -> bool {
57 self.token.alive.get()
58 }
59
60 pub fn is_dangling(&self) -> bool {
62 !self.is_alive()
63 }
64
65 pub fn token_ref_count(&self) -> usize {
67 Rc::strong_count(&self.token)
68 }
69}
70
71pub fn new_weak_pair<T>(value: T) -> (StrongOwner<T>, WeakRef<T>) {
73 StrongOwner::new(value)
74}
75
76pub fn weak_is_alive<T>(w: &WeakRef<T>) -> bool {
78 w.is_alive()
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 #[test]
86 fn test_alive_while_owner_exists() {
87 let (owner, weak) = StrongOwner::new(42);
88 assert!(weak.is_alive()); drop(owner);
90 }
91
92 #[test]
93 fn test_dangling_after_owner_drop() {
94 let (owner, weak) = StrongOwner::new(42);
95 drop(owner);
96 assert!(weak.is_dangling()); }
98
99 #[test]
100 fn test_get() {
101 let (owner, _weak) = StrongOwner::new(99);
102 assert_eq!(*owner.get(), 99); }
104
105 #[test]
106 fn test_is_alive_helper() {
107 let (_owner, weak) = StrongOwner::new(0);
108 assert!(weak_is_alive(&weak)); }
110
111 #[test]
112 fn test_new_pair_helper() {
113 let (_owner, weak) = new_weak_pair(1u32);
114 assert!(weak.is_alive()); }
116
117 #[test]
118 fn test_multiple_weakrefs_not_supported_directly() {
119 let (owner, weak) = StrongOwner::new("hello");
121 assert!(weak.is_alive());
122 drop(owner);
123 assert!(!weak.is_alive()); }
125
126 #[test]
127 fn test_token_ref_count_alive() {
128 let (_owner, weak) = StrongOwner::new(5);
129 assert_eq!(weak.token_ref_count(), 2); }
132
133 #[test]
134 fn test_token_ref_count_dead() {
135 let (owner, weak) = StrongOwner::new(5);
136 drop(owner);
137 assert_eq!(weak.token_ref_count(), 1); }
139
140 #[test]
141 fn test_is_not_dangling_when_alive() {
142 let (_owner, weak) = StrongOwner::new(0);
143 assert!(!weak.is_dangling()); }
145
146 #[test]
147 fn test_string_value() {
148 let (owner, weak) = StrongOwner::new(String::from("hello"));
149 assert_eq!(owner.get(), "hello");
150 drop(owner);
151 assert!(weak.is_dangling()); }
153}