Skip to content

Commit f8dd2b2

Browse files
committed
LockFreeLinkedSet: refactor to use SynchronizationObject
1 parent b109d90 commit f8dd2b2

File tree

3 files changed

+38
-37
lines changed

3 files changed

+38
-37
lines changed

lib/concurrent/edge/lock_free_linked_set.rb

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ def initialize(initial_size = 0, val = nil)
1414

1515
initial_size.times do
1616
val = block_given? ? yield : val
17-
18-
self.add val
17+
add val
1918
end
2019
end
2120

@@ -37,12 +36,12 @@ def add(item)
3736
pred, curr = window.pred, window.curr
3837

3938
# Item already in set
40-
if curr == item
41-
return false
42-
else
43-
node = Node.new item, curr
39+
return false if curr == item
40+
41+
node = Node.new item, curr
4442

45-
return true if pred.succ.compare_and_set curr, node, false, false
43+
if pred.SuccessorReference.compare_and_set curr, node, false, false
44+
return true
4645
end
4746
end
4847
end
@@ -73,8 +72,8 @@ def contains?(item)
7372
curr = @head
7473

7574
while curr < item
76-
curr = curr.next
77-
marked = curr.succ.marked?
75+
curr = curr.next_node
76+
marked = curr.SuccessorReference.marked?
7877
end
7978

8079
curr == item && !marked
@@ -92,18 +91,16 @@ def remove(item)
9291
window = Window.find @head, item
9392
pred, curr = window.pred, window.curr
9493

95-
if curr != item
96-
return false
97-
else
98-
succ = curr.next
99-
snip = curr.succ.compare_and_set succ, succ, false, true
94+
return false if curr != item
10095

101-
next unless snip
96+
succ = curr.next_node
97+
removed = curr.SuccessorReference.compare_and_set succ, succ, false, true
10298

103-
pred.succ.compare_and_set curr, succ, false, false
99+
next_node unless removed
104100

105-
return true
106-
end
101+
pred.SuccessorReference.compare_and_set curr, succ, false, false
102+
103+
return true
107104
end
108105
end
109106

@@ -121,10 +118,10 @@ def each
121118
curr = @head
122119

123120
until curr.last?
124-
curr = curr.next
125-
marked = curr.succ.marked?
121+
curr = curr.next_node
122+
marked = curr.SuccessorReference.marked?
126123

127-
yield curr.data if !marked
124+
yield curr.Data unless marked
128125
end
129126

130127
self

lib/concurrent/edge/lock_free_linked_set/node.rb

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,30 @@
33
module Concurrent
44
module Edge
55
class LockFreeLinkedSet
6-
class Node
6+
class Node < Synchronization::Object
77
include Comparable
88

9-
attr_reader :data, :succ, :key
9+
attr_reader :Data, :SuccessorReference, :Key
1010

11-
def initialize(data = nil, succ = nil)
12-
@succ = AtomicMarkableReference.new(succ || Tail.new)
13-
@data = data
14-
@key = key_for data
11+
def initialize(data = nil, successor = nil)
12+
super()
13+
14+
@SuccessorReference = AtomicMarkableReference.new(successor || Tail.new)
15+
@Data = data
16+
@Key = key_for data
17+
18+
ensure_ivar_visibility!
1519
end
1620

1721
# Check to see if the node is the last in the list.
1822
def last?
19-
@succ.value.is_a? Tail
23+
@SuccessorReference.value.is_a? Tail
2024
end
2125

2226
# Next node in the list. Note: this is not the AtomicMarkableReference
2327
# of the next node, this is the actual Node itself.
24-
def next
25-
@succ.value
28+
def next_node
29+
@SuccessorReference.value
2630
end
2731

2832
# This method provides a unqiue key for the data which will be used for
@@ -36,16 +40,16 @@ def key_for(data)
3640
# can be configurable in the future; for example, you could enforce a
3741
# split-ordering on the nodes in the set.
3842
def <=>(other)
39-
@key <=> other.hash
43+
@Key <=> other.hash
4044
end
4145
end
4246

4347
# Internal sentinel node for the Tail. It is always greater than all
4448
# other nodes, and it is self-referential; meaning its successor is
4549
# a self-loop.
4650
class Tail < Node
47-
def initialize(data = nil, _succ = nil)
48-
@succ = AtomicMarkableReference.new self
51+
def initialize(_data = nil, _succ = nil)
52+
@SuccessorReference = AtomicMarkableReference.new self
4953
end
5054

5155
# Always greater than other nodes. This means that traversal will end

lib/concurrent/edge/lock_free_linked_set/window.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,20 @@ def self.find(head, item)
1616
loop do
1717
break_inner_loops = false
1818
pred = head
19-
curr = pred.next
19+
curr = pred.next_node
2020

2121
loop do
22-
succ, marked = curr.succ.get
22+
succ, marked = curr.SuccessorReference.get
2323

2424
# Remove sequence of marked nodes
2525
while marked
26-
removed = pred.succ.compare_and_set curr, succ, false, false
26+
removed = pred.SuccessorReference.compare_and_set curr, succ, false, false
2727

2828
# If could not remove node, try again
2929
break_inner_loops = true && break unless removed
3030

3131
curr = succ
32-
succ, marked = curr.succ.get
32+
succ, marked = curr.SuccessorReference.get
3333
end
3434

3535
break if break_inner_loops

0 commit comments

Comments
 (0)