Commit 0160065c authored by Hai Dang's avatar Hai Dang
Browse files

rename NodePtr to NodeRef

parent 04e96ee9
Pipeline #42552 passed with stage
in 22 minutes and 46 seconds
......@@ -8,16 +8,16 @@ mod atomic_cell {
pub struct Node<'arena, T> {
data: T,
prev: AtomicCell<Option<NodePtr<'arena, T>>>,
next: AtomicCell<Option<NodePtr<'arena, T>>>,
prev: AtomicCell<Option<NodeRef<'arena, T>>>,
next: AtomicCell<Option<NodeRef<'arena, T>>>,
}
pub type NodePtr<'arena, T> = &'arena Node<'arena, T>;
pub type NodeRef<'arena, T> = &'arena Node<'arena, T>;
impl<'arena, T> Node<'arena, T> {
pub fn new(
data: T,
arena: &'arena TypedArena<Node<'arena, T>>,
) -> NodePtr<'arena, T> {
) -> NodeRef<'arena, T> {
arena.alloc(
Self {
data,
......@@ -28,7 +28,7 @@ mod atomic_cell {
}
/// Unlink the nodes adjacent to the provided node (but do not touch the node itself).
fn unlink(node: NodePtr<'arena, T>) {
fn unlink(node: NodeRef<'arena, T>) {
let old_prev = node.prev.load();
let old_next = node.next.load();
if let Some(next) = old_next {
......@@ -40,8 +40,8 @@ mod atomic_cell {
}
pub fn insert_next(
node: NodePtr<'arena, T>,
next: NodePtr<'arena, T>,
node: NodeRef<'arena, T>,
next: NodeRef<'arena, T>,
) {
// Step 1: unlink the prev and next pointers nodes adjacent to next.
Self::unlink(next);
......@@ -59,10 +59,10 @@ mod atomic_cell {
}
pub fn iterate(
node: NodePtr<'arena, T>,
node: NodeRef<'arena, T>,
f: impl Fn(&T),
) {
let mut cur: Option<NodePtr<'arena, T>> = Some(node);
let mut cur: Option<NodeRef<'arena, T>> = Some(node);
while let Some(node) = cur {
f(&node.data);
cur = node.next.load();
......@@ -74,8 +74,8 @@ mod atomic_cell {
pub fn init<'arena>(
arena: &'arena TypedArena<Node<'arena, u32>>,
list_size: u32,
) -> NodePtr<'arena, u32> {
let list: NodePtr<'arena, u32> = &*Node::new(0, &arena);
) -> NodeRef<'arena, u32> {
let list: NodeRef<'arena, u32> = &*Node::new(0, &arena);
let mut tail = list;
(1..list_size).for_each(|i| {
......@@ -89,7 +89,7 @@ mod atomic_cell {
pub fn par<'arena, T: Send + Sync>(
num_threads: usize,
list: &NodePtr<'arena, T>,
list: NodeRef<'arena, T>,
print: impl Fn(&T) + Sync,
) {
(0..num_threads)
......@@ -170,121 +170,6 @@ mod arc_ghost {
}
}
mod arc_rwlock {
use rayon::prelude::*;
use std::{
mem,
sync::{Arc, RwLock},
};
pub struct Node<T> {
data: T,
prev: Option<NodePtr<T>>,
next: Option<NodePtr<T>>,
}
pub type NodePtr<T> = Arc<RwLock<Node<T>>>;
impl<T> Drop for Node<T> {
fn drop(&mut self) {
let mut this: Option<NodePtr<_>> = self.next.take();
while let Some(node) = this.as_mut().and_then(Arc::get_mut) {
this = node.get_mut().ok().and_then(|node| node.next.take());
}
}
}
impl<T> Node<T> {
pub fn new(value: T) -> NodePtr<T> {
Arc::new(RwLock::new(
Self {
data: value,
prev: None,
next: None,
}
))
}
pub fn prev(&self) -> Option<NodePtr<T>> {
self.prev.clone()
}
pub fn next(&self) -> Option<NodePtr<T>> {
self.next.clone()
}
/// Unlink the nodes adjacent to `node`. The node will have `next` and `prev` be `None` after this.
pub fn remove(node: &NodePtr<T>) {
let mut node = node.write().unwrap();
let old_prev: Option<NodePtr<_>> = node.prev.take();
let old_next: Option<NodePtr<_>> = node.next.take();
if let Some(old_next) = &old_next {
// borrow both old_prev and old_next
// need to clone...
old_next.write().unwrap().prev = old_prev.clone();
}
if let Some(old_prev) = &old_prev {
old_prev.write().unwrap().next = old_next;
}
}
/// Insert `next` right after `node` in the list.
pub fn insert_next(
node: NodePtr<T>,
next: &NodePtr<T>
) {
// Step 1: unlink the prev and next pointers nodes adjacent to next.
Self::remove(next);
// Step 2: link node.next pointer and old_node_next.prev pointer to next.
let old_node_next: Option<NodePtr<T>> =
mem::replace(&mut node.write().unwrap().next, Some(next.clone()));
if let Some(old_node_next) = &old_node_next {
old_node_next.write().unwrap().prev = Some(next.clone());
}
// Step 3: link next to node and old_node_next.
let next: &mut Node<T> = &mut next.write().unwrap();
next.prev = Some(node);
next.next = old_node_next;
}
pub fn iterate(
node: &NodePtr<T>,
f: impl Fn(&T),
) {
let mut cur: Option<NodePtr<T>> = Some(node.clone());
while let Some(node) = cur {
let node: &Node<T> = &node.read().unwrap();
f(&node.data);
cur = node.next.clone();
}
}
}
/// Create a dlist segment.
pub fn init(list_size: u32) -> NodePtr<u32> {
let list: NodePtr<u32> = Node::new(0);
let mut tail = Some (list.clone());
(1..list_size).for_each(|i| {
let node = Node::new(i);
Node::insert_next(tail.take().unwrap(), &node);
tail = Some(node);
});
list
}
pub fn par<T: Send + Sync>(
num_threads: usize,
list: &NodePtr<T>,
f: impl Fn(&T) + Sync,
) {
(0..num_threads)
.into_par_iter()
.for_each(|_| Node::iterate(list, |n| f(n)));
}
}
mod arena_rwlock {
use rayon::prelude::*;
use std::{mem, sync::RwLock};
......@@ -292,16 +177,16 @@ mod arena_rwlock {
pub struct Node<'arena, T> {
data: T,
prev: Option<NodePtr<'arena, T>>,
next: Option<NodePtr<'arena, T>>,
prev: Option<NodeRef<'arena, T>>,
next: Option<NodeRef<'arena, T>>,
}
pub type NodePtr<'arena, T> = &'arena RwLock<Node<'arena, T>>;
pub type NodeRef<'arena, T> = &'arena RwLock<Node<'arena, T>>;
impl<'arena, T> Node<'arena, T> {
pub fn new(
value: T,
arena: &'arena TypedArena<RwLock<Node<'arena, T>>>
) -> NodePtr<'arena, T> {
) -> NodeRef<'arena, T> {
arena.alloc(RwLock::new(
Self {
data: value,
......@@ -311,19 +196,19 @@ mod arena_rwlock {
))
}
pub fn prev(&self) -> Option<NodePtr<'arena, T>> {
pub fn prev(&self) -> Option<NodeRef<'arena, T>> {
self.prev
}
pub fn next(&self) -> Option<NodePtr<'arena, T>> {
pub fn next(&self) -> Option<NodeRef<'arena, T>> {
self.next
}
/// Unlink the nodes adjacent to `node`. The node will have `next` and `prev` be `None` after this.
pub fn remove(node: &NodePtr<'arena, T>) {
pub fn remove(node: NodeRef<'arena, T>) {
let mut node = node.write().unwrap();
let old_prev: Option<NodePtr<_>> = node.prev.take();
let old_next: Option<NodePtr<_>> = node.next.take();
let old_prev: Option<NodeRef<_>> = node.prev.take();
let old_next: Option<NodeRef<_>> = node.next.take();
if let Some(old_next) = &old_next {
old_next.write().unwrap().prev = old_prev;
}
......@@ -334,14 +219,14 @@ mod arena_rwlock {
/// Insert `next` right after `node` in the list.
pub fn insert_next(
node: NodePtr<'arena, T>,
next: &NodePtr<'arena, T>
node: NodeRef<'arena, T>,
next: NodeRef<'arena, T>
) {
// Step 1: unlink the prev and next pointers nodes adjacent to next.
Self::remove(next);
// Step 2: link node.next pointer and old_node_next.prev pointer to next.
let old_node_next: Option<NodePtr<T>> =
let old_node_next: Option<NodeRef<T>> =
mem::replace(&mut node.write().unwrap().next, Some(next));
if let Some(old_node_next) = &old_node_next {
old_node_next.write().unwrap().prev = Some(next);
......@@ -354,10 +239,10 @@ mod arena_rwlock {
}
pub fn iterate(
node: &NodePtr<'arena, T>,
node: NodeRef<'arena, T>,
f: impl Fn(&T),
) {
let mut cur: Option<NodePtr<T>> = Some(node);
let mut cur: Option<NodeRef<T>> = Some(node);
while let Some(node) = cur {
let node: &Node<T> = &node.read().unwrap();
f(&node.data);
......@@ -368,8 +253,8 @@ mod arena_rwlock {
/// Create a dlist segment.
pub fn init<'arena>(
arena: &'arena TypedArena<RwLock<Node<'arena, u32>>>,
list_size: u32) -> NodePtr<'arena, u32> {
let list: NodePtr<'arena, u32> = &*Node::new(0, &arena);
list_size: u32) -> NodeRef<'arena, u32> {
let list: NodeRef<'arena, u32> = &*Node::new(0, &arena);
let mut tail = list;
(1..list_size).for_each(|i| {
......@@ -383,7 +268,7 @@ mod arena_rwlock {
pub fn par<'arena, T: Send + Sync>(
num_threads: usize,
list: &NodePtr<'arena, T>,
list: NodeRef<'arena, T>,
f: impl Fn(&T) + Sync,
) {
(0..num_threads)
......@@ -456,38 +341,23 @@ fn bench_dlist(c: &mut Criterion) {
});
});
// Memory leaks due to cycles on Arc!
// c.bench_function("dlist arc ghostcell init", |b| {
// GhostToken::new(|mut token| {
// b.iter(|| {
// black_box(arc_ghost::init(black_box(list_size), &mut token));
// })
// });
// });
// c.bench_function("dlist arc ghostcell par (×4)", |b| {
// GhostToken::new(|mut token| {
// let list = arc_ghost::init(list_size, &mut token);
// b.iter(|| {
// black_box(arc_ghost::par(4, &list, &token, |n| {
// black_box(n);
// }))
// });
// });
// });
// c.bench_function("dlist arc rwlock init", |b| {
// b.iter(|| {
// black_box(arc_rwlock::init(black_box(list_size)));
// })
// });
// c.bench_function("dlist arc rwlock par (×4)", |b| {
// let list = arc_rwlock::init(list_size);
// b.iter(|| {
// black_box(arc_rwlock::par(4, &list, |n| {
// black_box(n);
// }))
// });
// });
c.bench_function("dlist arc ghostcell init", |b| {
GhostToken::new(|mut token| {
b.iter(|| {
black_box(arc_ghost::init(black_box(list_size), &mut token));
})
});
});
c.bench_function("dlist arc ghostcell par (×4)", |b| {
GhostToken::new(|mut token| {
let list = arc_ghost::init(list_size, &mut token);
b.iter(|| {
black_box(arc_ghost::par(4, &list, &token, |n| {
black_box(n);
}))
});
});
});
}
criterion_group!(benches, bench_dlist);
......
......@@ -6,10 +6,10 @@ mod arena_rwlock {
pub struct Node<'arena, T> {
data: T,
prev: Option<NodePtr<'arena, T>>,
next: Option<NodePtr<'arena, T>>,
prev: Option<NodeRef<'arena, T>>,
next: Option<NodeRef<'arena, T>>,
}
pub type NodePtr<'arena, T> = &'arena RwLock<Node<'arena, T>>;
pub type NodeRef<'arena, T> = &'arena RwLock<Node<'arena, T>>;
impl<'arena, T> Node<'arena, T> {
pub fn new(value: T) -> Self {
......@@ -20,43 +20,43 @@ mod arena_rwlock {
}
}
pub fn alloc(self, arena: &'arena TypedArena<RwLock<Node<'arena, T>>>) -> NodePtr<'arena, T> {
pub fn alloc(self, arena: &'arena TypedArena<RwLock<Node<'arena, T>>>) -> NodeRef<'arena, T> {
arena.alloc(RwLock::new(self))
}
pub fn prev(&self) -> Option<NodePtr<'arena, T>> {
pub fn prev(&self) -> Option<NodeRef<'arena, T>> {
self.prev
}
pub fn next(&self) -> Option<NodePtr<'arena, T>> {
pub fn next(&self) -> Option<NodeRef<'arena, T>> {
self.next
}
/// Unlink the nodes adjacent to `node`. The node will have `next` and `prev` be `None` after this.
pub fn remove(node: &NodePtr<'arena, T>) {
pub fn remove(node: NodeRef<'arena, T>) {
let mut node = node.write().unwrap();
let old_prev: Option<NodePtr<_>> = node.prev.take();
let old_next: Option<NodePtr<_>> = node.next.take();
if let Some(old_next) = &old_next {
let old_prev: Option<NodeRef<_>> = node.prev.take();
let old_next: Option<NodeRef<_>> = node.next.take();
if let Some(old_next) = old_next {
old_next.write().unwrap().prev = old_prev;
}
if let Some(old_prev) = &old_prev {
if let Some(old_prev) = old_prev {
old_prev.write().unwrap().next = old_next;
}
}
/// Insert `next` right after `node` in the list.
pub fn insert_next(
node: NodePtr<'arena, T>,
next: &NodePtr<'arena, T>
node: NodeRef<'arena, T>,
next: NodeRef<'arena, T>
) {
// Step 1: unlink the prev and next pointers nodes adjacent to next.
Self::remove(next);
// Step 2: link node.next pointer and old_node_next.prev pointer to next.
let old_node_next: Option<NodePtr<T>> =
let old_node_next: Option<NodeRef<T>> =
mem::replace(&mut node.write().unwrap().next, Some(next));
if let Some(old_node_next) = &old_node_next {
if let Some(old_node_next) = old_node_next {
old_node_next.write().unwrap().prev = Some(next);
}
......@@ -67,10 +67,10 @@ mod arena_rwlock {
}
pub fn iterate(
node: &NodePtr<'arena, T>,
node: NodeRef<'arena, T>,
f: impl Fn(&T),
) {
let mut cur: Option<NodePtr<T>> = Some(node);
let mut cur: Option<NodeRef<T>> = Some(node);
while let Some(node) = cur {
let node: &Node<T> = &node.read().unwrap();
f(&node.data);
......@@ -81,8 +81,8 @@ mod arena_rwlock {
/// Create a dlist segment.
pub fn init<'arena>(
arena: &'arena TypedArena<RwLock<Node<'arena, u32>>>,
list_size: u32) -> NodePtr<'arena, u32> {
let list: NodePtr<'arena, u32> = &*Node::alloc(Node::new(0), &arena);
list_size: u32) -> NodeRef<'arena, u32> {
let list: NodeRef<'arena, u32> = &*Node::alloc(Node::new(0), &arena);
let mut tail = list;
(1..list_size).for_each(|i| {
......@@ -96,7 +96,7 @@ mod arena_rwlock {
pub fn par<'arena, T: Send + Sync>(
num_threads: usize,
list: &NodePtr<'arena, T>,
list: NodeRef<'arena, T>,
f: impl Fn(&T) + Sync,
) {
(0..num_threads)
......@@ -114,14 +114,14 @@ mod arc_rwlock {
pub struct Node<T> {
data: T,
prev: Option<NodePtr<T>>,
next: Option<NodePtr<T>>,
prev: Option<NodeRef<T>>,
next: Option<NodeRef<T>>,
}
pub type NodePtr<T> = Arc<RwLock<Node<T>>>;
pub type NodeRef<T> = Arc<RwLock<Node<T>>>;
impl<T> Drop for Node<T> {
fn drop(&mut self) {
let mut this: Option<NodePtr<_>> = self.next.take();
let mut this: Option<NodeRef<_>> = self.next.take();
while let Some(node) = this.as_mut().and_then(Arc::get_mut) {
this = node.get_mut().ok().and_then(|node| node.next.take());
}
......@@ -137,23 +137,23 @@ mod arc_rwlock {
}
}
pub fn alloc(self) -> NodePtr<T> {
pub fn alloc(self) -> NodeRef<T> {
Arc::new(RwLock::new(self))
}
pub fn prev(&self) -> Option<NodePtr<T>> {
pub fn prev(&self) -> Option<NodeRef<T>> {
self.prev.clone()
}
pub fn next(&self) -> Option<NodePtr<T>> {
pub fn next(&self) -> Option<NodeRef<T>> {
self.next.clone()
}
/// Unlink the nodes adjacent to `node`. The node will have `next` and `prev` be `None` after this.
pub fn remove(node: &NodePtr<T>) {
pub fn remove(node: &NodeRef<T>) {
let mut node = node.write().unwrap();
let old_prev: Option<NodePtr<_>> = node.prev.take();
let old_next: Option<NodePtr<_>> = node.next.take();
let old_prev: Option<NodeRef<_>> = node.prev.take();
let old_next: Option<NodeRef<_>> = node.next.take();
if let Some(old_next) = &old_next {
// borrow both old_prev and old_next
// need to clone...
......@@ -166,14 +166,14 @@ mod arc_rwlock {
/// Insert `next` right after `node` in the list.
pub fn insert_next(
node: NodePtr<T>,
next: &NodePtr<T>
node: NodeRef<T>,
next: &NodeRef<T>
) {
// Step 1: unlink the prev and next pointers nodes adjacent to next.
Self::remove(next);
// Step 2: link node.next pointer and old_node_next.prev pointer to next.
let old_node_next: Option<NodePtr<T>> =
let old_node_next: Option<NodeRef<T>> =
mem::replace(&mut node.write().unwrap().next, Some(next.clone()));
if let Some(old_node_next) = &old_node_next {
old_node_next.write().unwrap().prev = Some(next.clone());
......@@ -186,10 +186,10 @@ mod arc_rwlock {
}
pub fn iterate(
node: &NodePtr<T>,
node: &NodeRef<T>,
f: impl Fn(&T),
) {
let mut cur: Option<NodePtr<T>> = Some(node.clone());
let mut cur: Option<NodeRef<T>> = Some(node.clone());
while let Some(node) = cur {
let node: &Node<T> = &node.read().unwrap();
f(&node.data);
......@@ -198,8 +198,8 @@ mod arc_rwlock {
}
}
/// Create a dlist segment.
pub fn init(list_size: u32) -> NodePtr<u32> {
let list: NodePtr<u32> = Node::alloc(Node::new(0));
pub fn init(list_size: u32) -> NodeRef<u32> {
let list: NodeRef<u32> = Node::alloc(Node::new(0));
let mut tail = list.clone();
(1..list_size).for_each(|i| {
......@@ -214,7 +214,7 @@ mod arc_rwlock {
pub fn par<T: Send + Sync>(
num_threads: usize,
list: &NodePtr<T>,
list: &NodeRef<T>,
f: impl Fn(&T) + Sync,
) {
(0..num_threads)
......@@ -227,7 +227,7 @@ use std::fmt;
// use arc_rwlock::*;
// fn print_list<T: fmt::Debug>(list: &NodePtr<T>) {
// fn print_list<T: fmt::Debug>(list: &NodeRef<T>) {
// print!("[");
// Node::iterate(&list, |n| print!("{:?}, ", n));
// print!("]");
......@@ -256,7 +256,7 @@ use std::fmt;
use arena_rwlock::*;
use typed_arena::Arena as TypedArena;
fn print_list<'arena, T: fmt::Debug>(list: NodePtr<'arena, T>) {
fn print_list<'arena, T: fmt::Debug>(list: NodeRef<'arena, T>) {
print!("[");
Node::iterate(&list, |n| print!("{:?}, ", n));
print!("]");
......
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