For thread safe, bidirectional trees, the standard solution is to use Arc<Mutex<T>>
(and the corresponding Weak<Mutex<T>>
) for the links.
I was working on a project where the tree, once built, is readonly; after construction, not having the intermediate Mutex
considerably speeds up the access (by removing contention).
Currently, in order to achieve this, I use the nightly, unsafe, Arc::get_mut_unchecked()
API; the code is (roughly) the following:
pub fn new(mut children: Vec<Arc<Self>>) -> Arc<Self> {
let mut parent = Arc::new(Self {
parent: Weak::<Self>::new(),
children: vec![],
});
for child in children.iter_mut() {
let child_parent_ref = &mut unsafe { Arc::get_mut_unchecked(child) }.parent;
*child_parent_ref = Arc::downgrade(&parent);
}
let parent_mut = unsafe { Arc::get_mut_unchecked(&mut parent) };
parent_mut.children = children;
parent
}
Playground: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=bb30fc3247d486a357f805d02b3e3477
Is there a different (preferrably safer) strategy I can apply, in order to achieve this design?