1use std::fmt::Debug;
2use std::sync::{Arc, Mutex, Weak};
3
4pub struct Arcmo<T: Clone> {
7 inner: Arc<Mutex<Option<T>>>,
8}
9
10impl<T: Clone> Arcmo<T> {
11 pub fn none() -> Self {
13 Self {
14 inner: Arc::new(Mutex::new(None)),
15 }
16 }
17
18 pub fn some(value: T) -> Self {
20 Self {
21 inner: Arc::new(Mutex::new(Some(value))),
22 }
23 }
24
25 pub fn modify<F, R>(&self, f: F) -> R
29 where
30 T: Default,
31 F: FnOnce(&mut T) -> R,
32 {
33 let mut guard = self
34 .inner
35 .lock()
36 .unwrap_or_else(|poisoned| poisoned.into_inner());
37
38 match &mut *guard {
39 Some(value) => f(value),
40 None => {
41 let mut value = T::default();
42 let result = f(&mut value);
43 *guard = Some(value);
44 result
45 }
46 }
47 }
48
49 pub fn take(&self) -> Option<T> {
51 let mut guard = self
52 .inner
53 .lock()
54 .unwrap_or_else(|poisoned| poisoned.into_inner());
55 guard.take()
56 }
57
58 pub fn replace(&self, value: T) -> Option<T> {
60 let mut guard = self
61 .inner
62 .lock()
63 .unwrap_or_else(|poisoned| poisoned.into_inner());
64 guard.replace(value)
65 }
66
67 pub fn value(&self) -> Option<T> {
69 let guard = self
70 .inner
71 .lock()
72 .unwrap_or_else(|poisoned| poisoned.into_inner());
73 guard.clone()
74 }
75
76 pub fn is_some(&self) -> bool {
78 let guard = self
79 .inner
80 .lock()
81 .unwrap_or_else(|poisoned| poisoned.into_inner());
82 guard.is_some()
83 }
84
85 pub fn is_none(&self) -> bool {
87 let guard = self
88 .inner
89 .lock()
90 .unwrap_or_else(|poisoned| poisoned.into_inner());
91 guard.is_none()
92 }
93
94 pub fn downgrade(&self) -> WeakArcmo<T> {
96 WeakArcmo {
97 inner: Arc::downgrade(&self.inner),
98 }
99 }
100}
101
102impl<T: Clone> Clone for Arcmo<T> {
103 fn clone(&self) -> Self {
104 Self {
105 inner: Arc::clone(&self.inner),
106 }
107 }
108}
109
110impl<T: Clone + Debug> Debug for Arcmo<T> {
111 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112 f.debug_struct("Arcmo").field("inner", &self.inner).finish()
113 }
114}
115
116impl<T: Clone + Default> Default for Arcmo<T> {
117 fn default() -> Self {
118 Self::none()
119 }
120}
121
122pub struct WeakArcmo<T: Clone> {
124 inner: Weak<Mutex<Option<T>>>,
125}
126
127impl<T: Clone> WeakArcmo<T> {
128 pub fn modify<F, R>(&self, f: F) -> Option<R>
130 where
131 T: Default,
132 F: FnOnce(&mut T) -> R,
133 {
134 self.inner.upgrade().map(|arc| {
135 let mut guard = arc.lock().unwrap_or_else(|poisoned| poisoned.into_inner());
136 match &mut *guard {
137 Some(value) => f(value),
138 None => {
139 let mut value = T::default();
140 let result = f(&mut value);
141 *guard = Some(value);
142 result
143 }
144 }
145 })
146 }
147
148 pub fn value(&self) -> Option<T> {
150 self.inner.upgrade().and_then(|arc| match arc.lock() {
151 Ok(guard) => guard.clone(),
152 Err(poisoned) => poisoned.into_inner().clone(),
153 })
154 }
155
156 pub fn is_some(&self) -> bool {
158 self.inner
159 .upgrade()
160 .map(|arc| match arc.lock() {
161 Ok(guard) => guard.is_some(),
162 Err(poisoned) => poisoned.into_inner().is_some(),
163 })
164 .unwrap_or(false)
165 }
166
167 pub fn is_none(&self) -> bool {
169 !self.is_some()
170 }
171
172 pub fn replace(&self, value: T) -> Option<Option<T>> {
174 self.inner.upgrade().map(|arc| {
175 let mut guard = arc.lock().unwrap_or_else(|poisoned| poisoned.into_inner());
176 std::mem::replace(&mut *guard, Some(value))
177 })
178 }
179}
180
181impl<T: Clone> Debug for WeakArcmo<T> {
182 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
183 f.debug_struct("WeakArcmo")
184 .field("inner", &self.inner)
185 .finish()
186 }
187}
188
189#[cfg(test)]
190mod tests {
191 use super::*;
192 use std::panic::{self, AssertUnwindSafe};
193 use std::thread;
194
195 #[derive(Clone, Debug, Default, PartialEq)]
196 struct Settings {
197 enabled: bool,
198 count: i32,
199 name: String,
200 }
201
202 impl Settings {
203 fn update_timestamp(&mut self) {
204 self.count += 1;
205 }
206
207 fn recalculate_dependencies(&mut self) {
208 if self.enabled {
209 self.count *= 2;
210 }
211 }
212 }
213
214 #[test]
215 fn test_default() {
216 let arcmo: Arcmo<Vec<i32>> = Arcmo::default();
217 assert!(arcmo.is_none());
218
219 let int_arcmo: Arcmo<i32> = Arcmo::default();
220 assert!(int_arcmo.is_none());
221 }
222
223 #[test]
224 fn test_basic_usage() {
225 let v = Arcmo::some(1);
226 let result = v.modify(|v| {
227 *v = 42;
228 *v
229 });
230 assert_eq!(result, 42);
231 assert_eq!(v.value(), Some(42));
232 }
233
234 #[test]
235 fn test_modification_patterns() {
236 let state = Arcmo::none();
238 let new_state = Settings {
239 enabled: true,
240 count: 42,
241 name: "test".to_string(),
242 };
243 let result = state.modify(|s: &mut Settings| {
244 *s = new_state.clone();
245 s.count
246 });
247 assert_eq!(result, 42);
248 assert_eq!(state.value(), Some(new_state));
249
250 let counter = Arcmo::<Settings>::none();
252 let result = counter.modify(|s: &mut Settings| {
253 s.count += 1;
254 s.count
255 });
256 assert_eq!(result, 1);
257 assert_eq!(counter.value().unwrap().count, 1);
258
259 let vec = Arcmo::<Vec<i32>>::none();
261 let len = vec.modify(|v: &mut Vec<i32>| {
262 v.push(42);
263 v.len()
264 });
265 assert_eq!(len, 1);
266 assert_eq!(vec.value(), Some(vec![42]));
267
268 let settings = Arcmo::<Settings>::none();
270 let count = settings.modify(|s: &mut Settings| {
271 s.enabled = true;
272 s.update_timestamp();
273 s.recalculate_dependencies();
274 s.count
275 });
276 assert_eq!(count, 2); let result = settings.value().unwrap();
278 assert!(result.enabled);
279 assert_eq!(result.count, 2);
280 }
281
282 #[test]
283 fn test_take_and_replace() {
284 let v = Arcmo::some(1);
285 assert_eq!(v.take(), Some(1));
286 assert!(v.is_none());
287 assert_eq!(v.replace(42), None);
288 assert_eq!(v.value(), Some(42));
289 }
290
291 #[test]
292 fn test_multiple_references() {
293 let v1 = Arcmo::some(1);
294 let v2 = v1.clone();
295
296 let result = v1.modify(|v| {
297 *v = 42;
298 *v
299 });
300 assert_eq!(result, 42);
301 assert_eq!(v2.value(), Some(42));
302
303 v1.take();
304 assert!(v2.is_none());
305 }
306
307 #[test]
308 fn test_modify_none_uses_default() {
309 let settings: Arcmo<Settings> = Arcmo::none();
310
311 let count = settings.modify(|s: &mut Settings| {
312 assert!(!s.enabled);
313 assert_eq!(s.count, 0);
314 assert_eq!(s.name, "");
315 s.enabled = true;
316 s.count
317 });
318
319 assert_eq!(count, 0);
320 let result = settings.value().unwrap();
321 assert!(result.enabled);
322 assert_eq!(result.count, 0);
323 assert_eq!(result.name, "");
324 }
325
326 #[test]
327 fn test_weak_reference() {
328 let strong = Arcmo::some(42);
329 let weak = strong.downgrade();
330 assert_eq!(weak.value(), Some(42));
331 drop(strong);
332 assert_eq!(weak.value(), None);
333 }
334
335 #[test]
336 fn test_weak_with_none() {
337 let strong = Arcmo::none();
338 let weak = strong.downgrade();
339
340 assert_eq!(weak.value(), None);
341 assert!(weak.is_none());
342 assert!(!weak.is_some());
343
344 strong.replace(42);
345 assert_eq!(weak.value(), Some(42));
346 assert!(!weak.is_none());
347 assert!(weak.is_some());
348
349 strong.take();
350 assert_eq!(weak.value(), None);
351 assert!(weak.is_none());
352 assert!(!weak.is_some());
353 }
354
355 #[test]
356 fn test_weak_modification() {
357 let strong = Arcmo::some(vec![1, 2, 3]);
358 let weak = strong.downgrade();
359
360 let length = weak.modify(|v| {
362 v.push(4);
363 v.len()
364 });
365 assert_eq!(length, Some(4));
366 assert_eq!(strong.value(), Some(vec![1, 2, 3, 4]));
367
368 let strong = Arcmo::<Vec<i32>>::none();
370 let weak = strong.downgrade();
371 let len = weak.modify(|v| {
372 v.push(42);
373 v.len()
374 });
375 assert_eq!(len, Some(1));
376 assert_eq!(strong.value(), Some(vec![42]));
377
378 drop(strong);
380 let result = weak.modify(|v| {
381 v.push(5);
382 v.len()
383 });
384 assert_eq!(result, None);
385 }
386
387 #[test]
388 fn test_arcmo_poisoned_mutex_recovery() {
389 let arcmo = Arcmo::some(42);
390 let arcmo_clone = arcmo.clone();
391
392 let _ = panic::catch_unwind(AssertUnwindSafe(|| {
394 let handle = thread::spawn(move || {
395 arcmo_clone.modify(|_| panic!("Deliberate panic to poison mutex"));
397 });
398
399 let _ = handle.join();
401 }));
402
403 let value = arcmo.value();
405 assert_eq!(value, Some(42));
406
407 arcmo.modify(|v| *v = 100);
409 assert_eq!(arcmo.value(), Some(100));
410
411 assert!(arcmo.is_some());
413 assert!(!arcmo.is_none());
414
415 let taken = arcmo.take();
416 assert_eq!(taken, Some(100));
417 assert!(arcmo.is_none());
418
419 let replaced = arcmo.replace(200);
420 assert_eq!(replaced, None);
421 assert_eq!(arcmo.value(), Some(200));
422 }
423
424 #[test]
425 fn test_weak_arcmo_replace() {
426 let strong = Arcmo::some(42);
428 let weak = strong.downgrade();
429
430 let prev_value = weak.replace(100);
431 assert_eq!(prev_value, Some(Some(42))); assert_eq!(strong.value(), Some(100)); let strong_none = Arcmo::<i32>::none();
436 let weak_none = strong_none.downgrade();
437
438 let prev_value = weak_none.replace(200);
439 assert_eq!(prev_value, Some(None)); assert_eq!(strong_none.value(), Some(200)); drop(strong_none);
444 let result = weak_none.replace(300);
445 assert_eq!(result, None); }
447
448 #[test]
449 fn test_weak_arcmo_poisoned_mutex() {
450 let strong = Arcmo::some(42);
451 let weak = strong.downgrade();
452 let strong_clone = strong.clone();
453
454 let _ = panic::catch_unwind(AssertUnwindSafe(|| {
456 let handle = thread::spawn(move || {
457 strong_clone.modify(|_| panic!("Deliberate panic to poison mutex"));
458 });
459 let _ = handle.join();
460 }));
461
462 let value = weak.value();
464 assert_eq!(value, Some(42));
465
466 assert!(weak.is_some());
467 assert!(!weak.is_none());
468
469 let result = weak.modify(|v| {
470 *v = 100;
471 *v
472 });
473 assert_eq!(result, Some(100));
474 assert_eq!(strong.value(), Some(100));
475
476 let old_value = weak.replace(200);
478 assert_eq!(old_value, Some(Some(100)));
479 assert_eq!(strong.value(), Some(200));
480 }
481
482 #[test]
483 fn test_weak_arcmo_none_to_some() {
484 let strong = Arcmo::<i32>::none();
486 let weak = strong.downgrade();
487
488 assert!(strong.is_none());
489 assert!(weak.is_none());
490
491 let prev = weak.replace(42);
493 assert_eq!(prev, Some(None));
494 assert!(strong.is_some());
495 assert!(weak.is_some());
496 assert_eq!(strong.value(), Some(42));
497 }
498}