#![feature(arc_new_cyclic)]
//! Functions like Arc::new_cyclic which work for a varied number of arguments
pub mod arc {
use std::sync::{Arc, Weak};
pub fn new_cyclic_2(data_fn: impl FnOnce(&Weak, &Weak) -> (A, B)) -> (Arc, Arc) {
let mut b: Option> = None;
let a = Arc::new_cyclic(|weak_a| {
let mut a : Option = None;
b = Some(Arc::new_cyclic(|weak_b| {
let (a2, b2) = data_fn(weak_a, weak_b);
a = Some(a2);
b2
}));
a.unwrap()
});
(a, b.unwrap())
}
pub fn new_cyclic_3(data_fn: impl FnOnce(&Weak, &Weak, &Weak) -> (A, B, C)) -> (Arc, Arc, Arc) {
let mut c: Option> = None;
let mut b: Option> = None;
let a = Arc::new_cyclic(|weak_a| {
let mut a : Option = None;
b = Some(Arc::new_cyclic(|weak_b| {
let mut b: Option = None;
c = Some(Arc::new_cyclic(|weak_c| {
let (a2, b2, c2) = data_fn(weak_a, weak_b, weak_c);
a = Some(a2);
b = Some(b2);
c2
}));
b.unwrap()
}));
a.unwrap()
});
(a, b.unwrap(), c.unwrap())
}
}
#[cfg(test)]
mod tests {
use super::arc;
#[test]
fn arc_new_cyclic_2_immediate_upgrades_fail() {
arc::new_cyclic_2(|weak_a, weak_b| {
assert_eq!(weak_a.upgrade(), None);
assert_eq!(weak_b.upgrade(), None);
(1, 2)
});
}
#[test]
fn arc_new_cyclic_2_immediate_dereferences_pass() {
let (a, b) = arc::new_cyclic_2(|weak_a, weak_b| {
assert_eq!(weak_a.upgrade(), None);
assert_eq!(weak_b.upgrade(), None);
(1, 2)
});
assert_eq!(*a, 1);
assert_eq!(*b, 2);
}
#[test]
fn arc_new_cyclic_2_deferred_upgrades_fail() {
let mut a = None;
let mut b = None;
let stored = arc::new_cyclic_2(|weak_a, weak_b| {
a = Some(weak_a.clone());
b = Some(weak_b.clone());
(1, 2)
});
assert_eq!(*a.expect("Failed to store").upgrade().expect("Upgrade failed"), 1);
assert_eq!(*b.expect("Failed to store").upgrade().expect("Upgrade failed"), 2);
drop(stored);
}
#[test]
fn arc_new_cyclic_3_immediate_upgrades_fail() {
arc::new_cyclic_3(|weak_a, weak_b, weak_c| {
assert_eq!(weak_a.upgrade(), None);
assert_eq!(weak_b.upgrade(), None);
assert_eq!(weak_c.upgrade(), None);
(1, 2, 3)
});
}
#[test]
fn arc_new_cyclic_3_immediate_dereferences_pass() {
let (a, b, c) = arc::new_cyclic_3(|weak_a, weak_b, weak_c| {
assert_eq!(weak_a.upgrade(), None);
assert_eq!(weak_b.upgrade(), None);
assert_eq!(weak_c.upgrade(), None);
(1, 2, 3)
});
assert_eq!(*a, 1);
assert_eq!(*b, 2);
assert_eq!(*c, 3);
}
#[test]
fn arc_new_cyclic_3_deferred_upgrades() {
let mut a = None;
let mut b = None;
let mut c = None;
let stored = arc::new_cyclic_3(|weak_a, weak_b, weak_c| {
a = Some(weak_a.clone());
b = Some(weak_b.clone());
c = Some(weak_c.clone());
(1, 2, 3)
});
assert_eq!(*a.expect("Failed to store").upgrade().expect("Upgrade failed"), 1);
assert_eq!(*b.expect("Failed to store").upgrade().expect("Upgrade failed"), 2);
assert_eq!(*c.expect("Failed to store").upgrade().expect("Upgrade failed"), 3);
drop(stored);
}
}