Class: Concurrent::LockFreeQueue
Relationships & Source Files | |
Namespace Children | |
Classes:
| |
Super Chains via Extension / Inclusion / Inheritance | |
Class Chain:
|
|
Instance Chain:
|
|
Inherits: |
Concurrent::Synchronization::Object
|
Defined in: | lib/concurrent-ruby-edge/concurrent/edge/lock_free_queue.rb |
Class Attribute Summary
Synchronization::Object
- Inherited
Class Method Summary
- .new ⇒ LockFreeQueue constructor
Synchronization::Object
- Inherited
.atomic_attribute?, .atomic_attributes, | |
.attr_atomic | Creates methods for reading and writing to a instance variable with volatile (Java) semantic as |
.attr_volatile | Creates methods for reading and writing (as |
.ensure_safe_initialization_when_final_fields_are_present | For testing purposes, quite slow. |
.new | Has to be called by children. |
.safe_initialization!, .define_initialize_atomic_fields |
Synchronization::AbstractObject
- Inherited
Instance Method Summary
-
#compare_and_set_head(expected_head, new_head) ⇒ true, false
Sets the head to new_head if the current head is expected_head.
- #head ⇒ Object
-
#head=(new_head) ⇒ Object
Set
the head. - #pop
- #push(item)
-
#size
approximate.
-
#swap_head(new_head) ⇒ Object
Set
the head to new_head and return the old head. -
#update_head {|Object| ... } ⇒ Object
Updates the head using the block.
Synchronization::Object
- Inherited
Synchronization::Volatile
- Included
Synchronization::AbstractObject
- Inherited
Constructor Details
.new ⇒ LockFreeQueue
# File 'lib/concurrent-ruby-edge/concurrent/edge/lock_free_queue.rb', line 27
def initialize super() dummy_node = Node.new(:dummy, nil) self.head = dummy_node self.tail = dummy_node end
Instance Method Details
#compare_and_set_head(expected_head, new_head) ⇒ true
, false
Sets the head to new_head if the current head is expected_head
# File 'lib/concurrent-ruby-edge/concurrent/edge/lock_free_queue.rb', line 25
attr_atomic :head, :tail
#head ⇒ Object
# File 'lib/concurrent-ruby-edge/concurrent/edge/lock_free_queue.rb', line 25
attr_atomic :head, :tail
#head=(new_head) ⇒ Object
Set
the head.
# File 'lib/concurrent-ruby-edge/concurrent/edge/lock_free_queue.rb', line 25
attr_atomic :head, :tail
#pop
[ GitHub ]# File 'lib/concurrent-ruby-edge/concurrent/edge/lock_free_queue.rb', line 65
def pop # retry until some value can be returned while true # the value in @head is just a dummy node that always sits in that position, # the real 'head' is in its successor current_dummy_node = head current_tail_node = tail current_head_node = current_dummy_node.successor # if our local head is still consistent with the head node, continue # otherwise, start over if current_dummy_node == head # if either the queue is empty, or falling behind if current_dummy_node == current_tail_node # if there's nothing after the 'dummy' head node if current_head_node.nil? # just return nil return nil else # here the head element succeeding head is not nil, but the head and tail are equal # so tail is falling behind, update it, then start over compare_and_set_tail(current_tail_node, current_head_node) end # the queue isn't empty # if we can set the dummy head to the 'real' head, we're free to return the value in that real head, success elsif compare_and_set_head(current_dummy_node, current_head_node) # grab the item from the popped node item = current_head_node.item # return it, success! return item end end end end
#push(item)
[ GitHub ]# File 'lib/concurrent-ruby-edge/concurrent/edge/lock_free_queue.rb', line 35
def push(item) # allocate a new node with the item embedded new_node = Node.new(item, nil) # keep trying until the operation succeeds while true current_tail_node = tail current_tail_successor = current_tail_node.successor # if our stored tail is still the current tail if current_tail_node == tail # if that tail was really the last node if current_tail_successor.nil? # if we can update the previous successor of tail to point to this new node if current_tail_node.compare_and_set_successor(nil, new_node) # then update tail to point to this node as well compare_and_set_tail(current_tail_node, new_node) # and return return true # else, start the loop over end else # in this case, the tail ref we had wasn't the real tail # so we try to set its successor as the real tail, then start the loop again compare_and_set_tail(current_tail_node, current_tail_successor) end end end end
#size
approximate
# File 'lib/concurrent-ruby-edge/concurrent/edge/lock_free_queue.rb', line 104
def size successor = head.successor count = 0 while true break if successor.nil? current_node = successor successor = current_node.successor count += 1 end count end
#swap_head(new_head) ⇒ Object
Set
the head to new_head and return the old head.
# File 'lib/concurrent-ruby-edge/concurrent/edge/lock_free_queue.rb', line 25
attr_atomic :head, :tail
#update_head {|Object| ... } ⇒ Object
Updates the head using the block.
# File 'lib/concurrent-ruby-edge/concurrent/edge/lock_free_queue.rb', line 25
attr_atomic :head, :tail