Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
FP
ghostcell
Commits
04e96ee9
Commit
04e96ee9
authored
Feb 26, 2021
by
Ralf Jung
Browse files
use Weak refs for backlinks
parent
e40fd791
Pipeline
#42550
passed with stage
in 22 minutes and 37 seconds
Changes
4
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
ghostcell/benches/dlist.rs
View file @
04e96ee9
...
...
@@ -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
...
...
ghostcell/examples/dlist_arc.rs
View file @
04e96ee9
...
...
@@ -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
)
};
});
...
...
ghostcell/examples/dlist_arena_paper.rs
View file @
04e96ee9
...
...
@@ -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
)
{
...
...
ghostcell/src/dlist_arc.rs
View file @
04e96ee9
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
<
Weak
NodePtr
<
'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
<&
Weak
NodePtr
<
'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
.
tak
e
();
let
old_prev
:
Option
<
NodePtr
<
'id
,
T
>>
=
node
.prev
.
as_ref
()
.and_then
(|
p
|
p
.upgrad
e
()
)
;
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
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment