File: tuple.rb

package info (click to toggle)
ruby-concurrent 1.1.6%2Bdfsg-5
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 30,284 kB
  • sloc: ruby: 30,875; java: 6,117; javascript: 1,114; ansic: 288; makefile: 10; sh: 6
file content (86 lines) | stat: -rw-r--r-- 3,054 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
require 'concurrent/atomic/atomic_reference'

module Concurrent

  # A fixed size array with volatile (synchronized, thread safe) getters/setters.
  # Mixes in Ruby's `Enumerable` module for enhanced search, sort, and traversal.
  #
  # @example
  #   tuple = Concurrent::Tuple.new(16)
  #
  #   tuple.set(0, :foo)                   #=> :foo  | volatile write
  #   tuple.get(0)                         #=> :foo  | volatile read
  #   tuple.compare_and_set(0, :foo, :bar) #=> true  | strong CAS
  #   tuple.cas(0, :foo, :baz)             #=> false | strong CAS
  #   tuple.get(0)                         #=> :bar  | volatile read
  #
  # @see https://en.wikipedia.org/wiki/Tuple Tuple entry at Wikipedia
  # @see http://www.erlang.org/doc/reference_manual/data_types.html#id70396 Erlang Tuple
  # @see http://ruby-doc.org/core-2.2.2/Enumerable.html Enumerable
  class Tuple
    include Enumerable

    # The (fixed) size of the tuple.
    attr_reader :size

    # @!visibility private
    Tuple = defined?(Rubinius::Tuple) ? Rubinius::Tuple : ::Array
    private_constant :Tuple

    # Create a new tuple of the given size.
    #
    # @param [Integer] size the number of elements in the tuple
    def initialize(size)
      @size = size
      @tuple = tuple = Tuple.new(size)
      i = 0
      while i < size
        tuple[i] = Concurrent::AtomicReference.new
        i += 1
      end
    end

    # Get the value of the element at the given index.
    #
    # @param [Integer] i the index from which to retrieve the value
    # @return [Object] the value at the given index or nil if the index is out of bounds
    def get(i)
      return nil if i >= @size || i < 0
      @tuple[i].get
    end
    alias_method :volatile_get, :get

    # Set the element at the given index to the given value
    #
    # @param [Integer] i the index for the element to set
    # @param [Object] value the value to set at the given index
    #
    # @return [Object] the new value of the element at the given index or nil if the index is out of bounds
    def set(i, value)
      return nil if i >= @size || i < 0
      @tuple[i].set(value)
    end
    alias_method :volatile_set, :set

    # Set the value at the given index to the new value if and only if the current
    # value matches the given old value.
    #
    # @param [Integer] i the index for the element to set
    # @param [Object] old_value the value to compare against the current value
    # @param [Object] new_value the value to set at the given index
    #
    # @return [Boolean] true if the value at the given element was set else false
    def compare_and_set(i, old_value, new_value)
      return false if i >= @size || i < 0
      @tuple[i].compare_and_set(old_value, new_value)
    end
    alias_method :cas, :compare_and_set

    # Calls the given block once for each element in self, passing that element as a parameter.
    #
    # @yieldparam [Object] ref the `Concurrent::AtomicReference` object at the current index
    def each
      @tuple.each {|ref| yield ref.get}
    end
  end
end