Commit 04e96ee9 authored by Ralf Jung's avatar Ralf Jung
Browse files

use Weak refs for backlinks

parent e40fd791
Pipeline #42550 passed with stage
in 22 minutes and 37 seconds
......@@ -147,12 +147,12 @@ mod arc_ghost {
/// Create a dlist segment.
pub fn init<'id>(list_size: u32, token: &mut GhostToken<'id>) -> NodePtr<'id, u32> {
let list: NodePtr<u32> = Node::new(0);
let mut tail = Some (list.clone());
let mut tail = list.clone();
(1..list_size).for_each(|i| {
let node = Node::new(i);
Node::insert_next(tail.take().unwrap(), &node, token);
tail = Some(node);
Node::insert_next(&tail, node.clone(), token);
tail = node;
});
list
......
......@@ -11,16 +11,16 @@ fn print_list<'id, T: fmt::Debug>(tag: char, list: &NodePtr<'id, T>, token: &Gho
fn init_list<'id>(token: &mut GhostToken<'id>, list_size: u32) -> (NodePtr<'id, u32>, NodePtr<'id, u32>) {
let head: NodePtr<u32> = Node::new(0);
let mut tail = Some (head.clone());
let mut tail = head.clone();
// To append to the list, we need a &mut GhostToken
for i in 1..list_size {
let node = Node::new(i);
Node::insert_next(tail.take().unwrap(), &node, token);
tail = Some(node);
Node::insert_next(&tail, node.clone(), token);
tail = node;
};
(head, tail.unwrap())
(head, tail)
}
fn main() {
......@@ -52,7 +52,6 @@ fn main() {
// Mutation requires &mut GhostToken
(1..list_size / 2).for_each(|_| {
if let Some(prev) = tail.borrow(&token).prev() {
let prev = prev.clone();
Node::remove(&prev, &mut token)
};
});
......
......@@ -2,7 +2,7 @@ use ghostcell::dlist_arena::*;
use typed_arena::Arena as TypedArena;
use ghostcell::GhostToken;
use std::sync::RwLock;
use std::{fmt, thread, time};
use std::fmt;
fn print_list<'arena, 'id, T: fmt::Debug>(tag: char, list: NodeRef<'arena, 'id, T>, token: &GhostToken<'id>) {
for d in Node::iter(list, token) {
......
use crate::{GhostCell, GhostToken};
use std::{mem, sync::Arc};
use std::sync::{Arc, Weak};
pub struct Node<'id, T> {
data: T,
prev: Option<NodePtr<'id, T>>,
prev: Option<WeakNodePtr<'id, T>>,
next: Option<NodePtr<'id, T>>,
}
pub type WeakNodePtr<'id, T> = Weak<GhostCell<'id, Node<'id, T>>>;
pub type NodePtr<'id, T> = Arc<GhostCell<'id, Node<'id, T>>>;
impl<'id, T> Node<'id, T> {
......@@ -19,10 +20,14 @@ impl<'id, T> Node<'id, T> {
))
}
pub fn prev(&self) -> Option<&NodePtr<'id, T>> {
pub fn prev_weak(&self) -> Option<&WeakNodePtr<'id, T>> {
self.prev.as_ref()
}
pub fn prev(&self) -> Option<NodePtr<'id, T>> {
self.prev_weak().and_then(|p| p.upgrade())
}
pub fn next(&self) -> Option<&NodePtr<'id, T>> {
self.next.as_ref()
}
......@@ -31,13 +36,11 @@ impl<'id, T> Node<'id, T> {
pub fn remove<'a>(node: &NodePtr<'id, T>, token: &'a mut GhostToken<'id>) {
// `take` both pointers from `node`, setting its fields to `None`.
let node = node.borrow_mut(token);
let old_prev: Option<NodePtr<'id, T>> = node.prev.take();
let old_prev: Option<NodePtr<'id, T>> = node.prev.as_ref().and_then(|p| p.upgrade());
let old_next: Option<NodePtr<'id, T>> = node.next.take();
// link `old_prev` and `old_next together
if let Some(old_next) = &old_next {
// borrow both old_prev and old_next
// need to clone...
old_next.borrow_mut(token).prev = old_prev.clone();
old_next.borrow_mut(token).prev = old_prev.as_ref().map(|p| Arc::downgrade(&p));
}
if let Some(old_prev) = &old_prev {
old_prev.borrow_mut(token).next = old_next;
......@@ -46,27 +49,27 @@ impl<'id, T> Node<'id, T> {
/// Insert `next` right after `node` in the list.
pub fn insert_next<'a>(
node1: NodePtr<'id, T>,
node2: &NodePtr<'id, T>,
node1: &NodePtr<'id, T>,
node2: NodePtr<'id, T>,
token: &'a mut GhostToken<'id>,
) {
// Step 1: unlink the prev and next pointers of nodes that are
// adjacent to node2.
Self::remove(node2, token);
Self::remove(&node2, token);
// Step 2: swap node1.next pointer to node2, and get out the old
// next pointer as node1_old_next, and let node1_old_next.prev
// point to node2.
let node1_old_next: Option<NodePtr<'id, T>> =
mem::replace(&mut node1.borrow_mut(token).next, Some(node2.clone()));
// Step 2: get out the old next pointer as node1_old_next.
let node1_old_next: Option<NodePtr<'id, T>> = node1.borrow_mut(token).next.take();
if let Some(node1_old_next) = &node1_old_next {
node1_old_next.borrow_mut(token).prev = Some(node2.clone());
node1_old_next.borrow_mut(token).prev = Some(Arc::downgrade(&node2));
}
// Step 3: link node2 to node1 and node1_old_next.
let node2: &mut Node<'id, T> = node2.borrow_mut(token);
node2.prev = Some(node1);
node2.next = node1_old_next;
let node2_inner: &mut Node<'id, T> = node2.borrow_mut(token);
node2_inner.prev = Some(Arc::downgrade(node1));
node2_inner.next = node1_old_next;
// Step 4: Link node1.next to node2.
node1.borrow_mut(token).next = Some(node2);
}
/// Traverse immutably
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment