Commit 2bd6f359 authored by Hai Dang's avatar Hai Dang
Browse files

remove linked list examples and benchmark

parent e1cc0c20
Pipeline #42808 passed with stage
in 22 minutes and 54 seconds
......@@ -10,10 +10,6 @@ edition = "2018"
name = "dlist"
harness = false
[[bench]]
name = "linked_list"
harness = false
[dependencies]
typed-arena = "2.0.1"
......
This diff is collapsed.
use ghostcell::{GhostCell, GhostToken};
use std::{
fmt,
sync::Arc,
sync::RwLock,
mem,
ops::Deref,
ops::DerefMut,
};
use rayon;
/// The Arc<GhostCell> Example from §4 of the paper.
/// Run from the `./ghostcell-examples` directory, with the command
/// `cargo run --example linked_list_arc_ghostcell`.
struct Node<'id, T> {
data: T,
next: Option<Arc<GhostCell<'id, Node<'id, T>>>>,
}
type NodePtr<'id, T> = Arc<GhostCell<'id, Node<'id, T>>>;
fn reverse<'id, T>(mut list: NodePtr<'id, T>, token: &mut GhostToken<'id>)
-> NodePtr<'id, T> {
let mut reversed : Option<NodePtr<'id, T>> = None;
loop {
let inner : &mut Node<'id, T> = list.borrow_mut(token);
let old_next : Option<NodePtr<'id, T>> =
mem::replace(&mut inner.next, reversed);
reversed = Some(list);
if let Some(old_next) = old_next {
list = old_next;
} else {
return reversed.unwrap(); // We know the reversed list will end up nonempty.
}
}
}
fn iterate<'id, B, T>(list: &NodePtr<'id, T>, token: &GhostToken<'id>,
mut acc: B, f: fn(B, &T) -> B) -> B {
let mut cur : Option<&GhostCell<'id, Node<'id, T>>> = Some(&*list);
while let Some(node) = cur {
let inner : &Node<'id, T> = node.borrow(token); // immutably borrow `node` with `token`
acc = f(acc, &inner.data);
cur = inner.next.as_deref();
}
acc
}
fn init<'id>(list_size: u32) -> Arc<GhostCell<'id, Node<'id, u32>>> {
let mut numbers = Node { data: 0, next: None };
for i in 1..list_size {
numbers = Node {
data: i,
next: Some(Arc::new(GhostCell::new(numbers))),
};
}
Arc::new(GhostCell::new(numbers))
}
#[allow(unused)]
fn cons<'id, T>(head: T, tail: &NodePtr<'id, T>) -> NodePtr<'id, T> {
Arc::new(GhostCell::new(Node { data: head, next: Some(Arc::clone(tail)) }))
}
fn print_list<'id, T: fmt::Debug>(list: &NodePtr<'id, T>, token: &GhostToken<'id>) {
print!("[");
iterate(list, token, 0, |acc, d|{ print!("{:?}, ", d) ; acc });
print!("]");
}
fn full_par_ghostcell(list_size: u32) {
GhostToken::new(|mut token| {
let list : Arc<GhostCell<Node<u32>>> = init(list_size);
let (sum, len) = rayon::join(
|| iterate(&list, &token, 0, |acc, x| acc + x),
|| iterate(&list, &token, 0, |acc, _| acc + 1)
);
let reversed = reverse(list, &mut token);
println!("Sum: {:}, Len: {:}", sum, len);
print_list(&reversed, &token);
});
}
fn full_rwlock_ghost_token(list_size: u32) {
GhostToken::new(|token| {
let wlist : Arc<GhostCell<Node<u32>>> = init(list_size);
let rlist = wlist.clone();
let lock = RwLock::new(token);
let _ = rayon::join(
|| {
let mut guard = lock.write().unwrap();
let reversed = reverse(wlist, guard.deref_mut());
print_list(&reversed, guard.deref());
},
|| {
let guard = lock.read().unwrap();
let sum = iterate(&rlist, guard.deref(), 0, |acc, x| acc + x);
println!("Sum: {:}", sum);
}
);
});
}
pub fn main() {
full_par_ghostcell(10);
full_rwlock_ghost_token(10);
}
use std::{
fmt,
sync::Arc,
sync::RwLock,
sync::RwLockWriteGuard,
sync::RwLockReadGuard,
mem,
ops::Deref,
ops::DerefMut,
};
use rayon;
/// The Arc<RwLock> Example from §3 and §4.3 of the paper.
/// Run from the `./ghostcell-examples` directory, with the command
/// `cargo run --example linked_list_arc_rwlock`.
struct Node<T> {
data: T,
next: Option<Arc<RwLock<Node<T>>>>
}
type NodePtr<T> = Arc<RwLock<Node<T>>>;
fn init(list_size: u32) -> NodePtr<u32> {
let mut numbers = Node { data: 0, next: None };
for i in 1..list_size {
numbers = Node {
data: i,
next: Some(Arc::new(RwLock::new(numbers))),
};
}
Arc::new(RwLock::new(numbers))
}
// List cons (not consuming the tail).
#[allow(unused)]
fn cons<T>(head: T, tail: &NodePtr<T>) -> NodePtr<T> {
Arc::new(RwLock::new(Node { data: head, next: Some(Arc::clone(tail)) }))
}
fn reverse<T>(mut list: NodePtr<T>) -> NodePtr<T> {
let mut reversed : Option<NodePtr<T>> = None;
loop {
let old_next : Option<NodePtr<T>> = {
// tie the mutable borrow of the current node to `guard`
let mut guard : RwLockWriteGuard<Node<T>> = list.deref().write().unwrap();
mem::replace(&mut guard.deref_mut().next, reversed)
}; // the mutable borrow ends here as `guard` goes out of scope
reversed = Some(list);
if let Some(old_next) = old_next {
list = old_next;
} else {
return reversed.unwrap(); // We know the reversed list will end up nonempty.
}
}
}
fn iterate<B, T>(list: &NodePtr<T>, mut acc: B, f: fn(B, &T) -> B) -> B {
let mut cur : Option<NodePtr<T>> = Some(list.clone());
while let Some(node) = cur {
let guard : RwLockReadGuard<Node<T>> = node.deref().read().unwrap();
acc = f(acc, &guard.deref().data);
cur = guard.deref().next.clone();
}
acc
}
fn print_list<T: fmt::Debug>(list: &NodePtr<T>) {
print!("[");
iterate(list, 0, |acc, d|{ print!("{:?}, ", d) ; acc });
print!("]");
}
fn full_par_rwlock(list_size: u32) {
let list : Arc<RwLock<Node<u32>>> = init(list_size);
let (sum, len) = rayon::join(
|| iterate(&list, 0, |acc, x| acc + x),
|| iterate(&list, 0, |acc, _| acc + 1)
);
let reversed = reverse(list);
println!("Sum: {:}, Len: {:}", sum, len);
print_list(&reversed);
}
pub fn main() {
full_par_rwlock(10);
}
use ghostcell::{GhostCell, GhostToken};
use std::{fmt, mem};
use typed_arena::Arena as TypedArena;
#[derive(Clone, Copy)]
struct Node<'arena, 'id, T> {
data: T,
next: Option<&'arena GhostCell<'id, Node<'arena, 'id, T>>>,
}
pub fn main() {
GhostToken::new(|mut token| {
// let mut arena = Arena::with_capacity(10 * mem::size_of::<Node<u32>>());
// let mut arena = arena.allocator();
let arena = TypedArena::with_capacity(10);
let mut numbers = Node {
data: 0,
next: None,
};
// Create a linked list segment.
for i in 1..10 {
numbers = Node {
data: i,
next: Some(GhostCell::from_mut(arena.alloc(numbers))),
};
}
let mut list = &GhostCell::new(numbers);
print!("Numbers: ");
print_list(Some(&*list), &token);
// Reverse the list.
let mut reversed = None;
loop {
let next = {
let node = list.borrow_mut(&mut token);
mem::replace(&mut node.next, reversed)
};
reversed = Some(list);
if let Some(next) = next {
list = next;
} else {
break;
}
}
print!("Reverse: ");
print_list(reversed, &token);
});
}
fn print_list<'arena, 'id, T: fmt::Debug>(
mut list: Option<&GhostCell<'id, Node<'arena, 'id, T>>>,
token: &GhostToken<'id>,
) {
print!("[");
while let Some(node) = list {
let node = node.borrow(token);
print!("{:?}, ", node.data);
list = node.next;
}
println!("]");
}
use std::{
fmt,
mem,
};
use typed_arena::Arena as TypedArena;
use ghostcell::{GhostCell, GhostToken};
struct Node<'arena, 'id, T> {
data: T,
next: Option<&'arena GhostCell<'id, Node<'arena, 'id, T>>>,
}
fn reverse<'arena, 'id, T>(
mut list: &'arena GhostCell<'id, Node<'arena, 'id, T>>,
token: &mut GhostToken<'id>)
-> &'arena GhostCell<'id, Node<'arena, 'id, T>> {
let mut reversed : Option<&'arena GhostCell<'id, Node<'arena, 'id, T>>> = None;
loop {
let old_next : Option<&'arena GhostCell<'id, Node<'arena, 'id, T>>> = {
let guard : &mut Node<'arena, 'id, T> = list.borrow_mut(token);
mem::replace(&mut guard.next, reversed)
};
reversed = Some(list);
if let Some(old_next) = old_next {
list = old_next;
} else {
return reversed.unwrap(); // We know the reversed list will end up nonempty.
}
}
}
fn fold_list<'arena, 'id, B, T>(
list: &GhostCell<'id, Node<'arena, 'id, T>>,
token: &GhostToken<'id>,
mut acc: B, mut f: impl FnMut(B, &T) -> B) -> B
{
let mut cur : Option<&GhostCell<'id, Node<'arena, 'id, T>>> = Some(list);
while let Some(node) = cur {
let guard : &Node<'arena, 'id,T> = node.borrow(token);
acc = f(acc, &guard.data);
cur = guard.next;
}
acc
}
fn do_list<'arena, 'id, T>(
list: &GhostCell<'id, Node<'arena, 'id, T>>,
token: &GhostToken<'id>, f: fn(&T)) {
let mut cur : Option<&GhostCell<'id, Node<'arena, 'id, T>>> = Some(list);
while let Some(node) = cur {
let guard : &Node<'arena, 'id,T> = node.borrow(token); // immutably borrow `node` with `token`
f(&guard.data);
cur = guard.next;
}
}
fn print_list<'arena, 'id, T: fmt::Debug>(
list: &GhostCell<'id, Node<'arena, 'id, T>>,
token: &GhostToken<'id>) {
print!("[");
do_list(list, token, |d|{ print!("{:?}, ", d) });
print!("]");
}
fn init<'arena, 'id>(arena: &'arena TypedArena<Node<'arena, 'id, u32>>, list_size: u32)
-> &'arena GhostCell<'id, Node<'arena, 'id, u32>>
{
let mut numbers = Node { data: 0, next: None };
for i in 1..list_size {
numbers = Node {
data: i,
next: Some(GhostCell::from_mut(arena.alloc(numbers))),
};
}
GhostCell::from_mut(arena.alloc(numbers))
}
fn main() {
GhostToken::new(|mut token| {
let list_size = 10;
let arena = TypedArena::with_capacity(list_size as usize);
// Create a linked list segment.
let list = init(&arena, list_size);
print!("Numbers: ");
print_list(&list, &token);
let sum = fold_list(list, &token, 0, |acc, n| acc + n);
println!("Sum {:?}", sum);
let reversed = reverse(list, &mut token);
let len = fold_list(reversed, &token, 0, |acc, _| acc + 1);
println!("Len {:?}", len);
});
}
use ghostcell::{GhostCell, GhostToken};
use std::{fmt, mem};
use typed_arena::Arena as TypedArena;
#[derive(Clone, Copy)]
struct Node<'arena, 'id, T> {
data: T,
next: Option<&'arena GhostCell<'id, Node<'arena, 'id, T>>>,
}
pub fn main() {
GhostToken::new(|mut token| {
//let mut arena = Arena::with_capacity(10 * mem::size_of::<Node<u32>>());
// let mut arena = arena.allocator();
let arena = TypedArena::with_capacity(10);
let mut numbers = Node {
data: 1,
next: None,
};
// Create a linked list segment.
for i in 2..11 {
numbers = Node {
data: i,
next: Some(GhostCell::from_mut(arena.alloc(numbers))),
};
}
let mut list = &GhostCell::new(numbers);
print!("Numbers: ");
print_list(Some(&*list), &token);
let (sum, len) = rayon::join(
|| fold_list(Some(&*list), &token, 0, |acc, x| acc + x),
|| fold_list(Some(&*list), &token, 0, |acc, _| acc + 1),
);
println!("Sum: {:?}, Product: {:?}", sum, len);
// Reverse the list.
let mut reversed = None;
loop {
let next = {
let node = list.borrow_mut(&mut token);
mem::replace(&mut node.next, reversed)
};
reversed = Some(list);
if let Some(next) = next {
list = next;
} else {
break;
}
}
print!("Reverse: ");
print_list(reversed, &token);
});
}
fn fold_list<'arena, 'id, T, B>(
mut list: Option<&GhostCell<'id, Node<'arena, 'id, T>>>,
token: &GhostToken<'id>,
init: B,
mut reduce: impl FnMut(B, &T) -> B,
) -> B {
let mut acc = init;
while let Some(node) = list {
let node = node.borrow(token);
acc = reduce(acc, &node.data);
list = node.next;
}
acc
}
fn print_list<'arena, 'id, T: fmt::Debug>(
mut list: Option<&GhostCell<'id, Node<'arena, 'id, T>>>,
token: &GhostToken<'id>,
) {
print!("[");
while let Some(node) = list {
let node = node.borrow(token);
print!("{:?}, ", node.data);
list = node.next;
}
println!("]");
}
use std::{borrow::BorrowMut, fmt, mem};
struct Node<T> {
data: T,
next: Option<Box<Node<T>>>,
}
pub fn main() {
let mut numbers = Node {
data: 0,
next: None,
};
// Create a linked list segment.
for i in 1..10 {
numbers = Node {
data: i,
next: Some(Box::new(numbers)),
};
}
let mut list = Box::new(numbers);
print!("Numbers: ");
print_list(Some(&*list));
// Reverse the list.
let mut reversed = None;
loop {
let next = {
let node: &mut Node<_> = list.borrow_mut();
mem::replace(&mut node.next, reversed)
};
reversed = Some(list);
if let Some(next) = next {
list = next;
} else {
break;
}
}
print!("Reverse: ");
print_list(reversed.as_deref());
}
fn print_list<T: fmt::Debug>(mut list: Option<&Node<T>>) {
print!("[");
while let Some(node) = list {
print!("{:?}, ", node.data);
list = node.next.as_deref();
}
println!("]");
}
use std::{fmt, rc::Rc};
struct Node<T> {
data: T,
next: Option<Rc<Node<T>>>,
}
pub fn main() {
let mut numbers = Node {
data: 0,
next: None,
};
// Create a linked list segment.
for i in 1..10 {
numbers = Node {
data: i,
next: Some(Rc::new(numbers)),
};
}
let list = Rc::new(numbers);
print!("Numbers: ");
print_list(Some(&*list));
}
fn print_list<T: fmt::Debug>(mut list: Option<&Node<T>>) {
print!("[");
while let Some(node) = list {
print!("{:?}, ", node.data);
list = node.next.as_deref();
}
println!("]");
}
use ghostcell::{GhostCell, GhostToken};
use std::{fmt, mem, rc::Rc};
struct Node<'id, T> {
data: T,
next: Option<Rc<GhostCell<'id, Node<'id, T>>>>,
}
pub fn main() {
GhostToken::new(|mut token| {
let mut numbers = Node {
data: 0,
next: None,
};
// Create a linked list segment.
for i in 1..10 {
numbers = Node {
data: i,
next: Some(Rc::new(GhostCell::new(numbers))),
};
}
let mut list = Rc::new(GhostCell::new(numbers));
print!("Numbers: ");
print_list(Some(&*list), &token);
// Reverse the list.
let mut reversed = None;
loop {
let next = {
let node = list.borrow_mut(&mut token);
mem::replace(&mut node.next, reversed)
};
reversed = Some(list);
if let Some(next) = next {
list = next;
} else {
break;
}
}