Class: Farce::Transaction::Vector

Inherits:
Abstract::Vector show all
Defined in:
lib/farce/transaction/vector.rb

Overview

A Vector that is part of a transaction.

Instance Method Summary collapse

Methods included from Unshareable

#initialize, #ractor_shareable?

Methods inherited from Abstract::Vector

#&, #*, #+, #-, #<=>, #append, #as_extended_json, #as_json, #assoc, #at, #bsearch, #bsearch_index, #bson_type, #chunk, #chunk_while, #combination, #compact, #compact!, #compact_blank, #concat, #deconstruct, #deep_dup, #delete, #delete_at, #delete_if, #difference, #dig, #drop, #drop_while, #each_cons, #each_index, #each_slice, #entries, #excluding, #fetch, #fetch_values, #fifth, #fill, #filter_map, #first, #flat_map, #flatten, #flatten!, #forty_two, #fourth, #from, #grep, #grep_v, #group_by, #in_groups, #in_groups_of, #in_order_of, #include?, #including, #index, #inquiry, #insert, #intersect?, #intersection, #keep_if, #last, #map, #map!, #max, #max_by, #maximum, #min, #min_by, #minimum, #minmax, #minmax_by, #pack, #partition, #permutation, #pick, #pluck, #product, #rassoc, #reject, #reject!, #repeated_combination, #repeated_permutation, #replace, #reverse, #reverse!, #reverse_each, #rfind, #rindex, #rotate, #rotate!, #sample, #second, #second_to_last, #select, #select!, #shift, #shuffle, #shuffle!, #slice, #slice!, #slice_after, #slice_before, #slice_when, #sort, #sort!, #sort_by, #sort_by!, #split, #take, #take_while, #third, #third_to_last, #to, #to_a, #to_ary, #to_bson, #to_bson_normalized_value, #to_cbor, #to_fs, #to_h, #to_json, #to_msgpack, #to_param, #to_query, #to_sentence, #to_xml, #transpose, #union, #uniq, #uniq!, #unshift, #values_at, #wait_until, #wait_until_changed, #wait_until_match, #wait_until_non_nil, #wait_until_value, #wait_while, #wait_while_match, #wait_while_value, #zip, #|

Methods inherited from Abstract::Collection

[], #count, #filter, #include?, #join, #length, #member?, #reject, #select, #to_a, #to_s

Methods included from Internal::Copyable

#duplicable?

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Farce::Transaction::Wrapper

Instance Method Details

#<<(value) ⇒ BasicObject



75
# File 'lib/farce/transaction/vector.rb', line 75

def <<(value) = push(value)

#[](index, length = UNDEFINED) ⇒ BasicObject, ...

Read an index without waiting for atomic-update access, or return a slice snapshot.

Parameters:

  • index (Integer, Range) —

    The index, start index, or range. Negative indexes count from the end.

  • length (Integer) (defaults to: UNDEFINED) —

    The slice length. Omit for a single index or range.

Returns:

  • (BasicObject, Vector, nil) —

    The logical value, a slice Vector, or nil if absent.

See Also:



21
22
23
24
25
26
# File 'lib/farce/transaction/vector.rb', line 21

def [](index, length = UNDEFINED)
  access do
    next unwrap_stored(@working[index]) if length.equal?(UNDEFINED) && !index.is_a?(Range)
    slice(index, length)
  end
end

#[]=(index, value, replacement = UNDEFINED) ⇒ BasicObject

Store a value or replace a slice atomically, growing the vector if necessary. Slice replacements accept a Vector, Array-like object, or one scalar value.

Parameters:

  • index (Integer, Range) —

    The index, start index, or range.

  • value (BasicObject, Integer) —

    The assigned value, or the slice length for three arguments.

  • replacement (BasicObject) (defaults to: UNDEFINED) —

    The replacement for the three-argument form.

Returns:

  • (BasicObject) —

    The assigned value or replacement sequence.

See Also:



42
43
44
45
46
47
48
# File 'lib/farce/transaction/vector.rb', line 42

def []=(index, value, replacement = UNDEFINED)
  if replacement.equal?(UNDEFINED) && !index.is_a?(Range)
    store(index, value)
  else
    write { assign_vector_slice(index, value, replacement) }
  end
end

#clear ⇒ self

Remove all slots.

Returns:

  • (self)

See Also:



85
86
87
88
# File 'lib/farce/transaction/vector.rb', line 85

def clear
  write { @working.clear }
  self
end

#compare_and_set(index, expected, replacement, mode: nil) ⇒ Boolean

Replace an existing index only if its value matches the expected value. This never grows the vector. Matching uses the configured comparison mode.

Parameters:

  • index (Integer) —

    The index. Negative indexes count from the end.

  • expected (BasicObject) —

    The value that must match the current entry.

  • replacement (BasicObject) —

    The value to store on a match.

  • timeout (Numeric, nil) —

    The maximum wait in seconds. Nil waits indefinitely.

Returns:

  • (Boolean) —

    Whether the replacement succeeded. False on timeout.

See Also:



125
126
127
128
129
130
131
132
133
134
# File 'lib/farce/transaction/vector.rb', line 125

def compare_and_set(index, expected, replacement, mode: nil)
  write do
    next compared(@working.compare_and_set(index, expected, replacement)) unless @manager
    index = Integer(index)
    next compared(false) unless index >= -@working.size && index < @working.size &&
      matches?(@working[index], expected, identity: @object.compare_by_identity?)
    @working.store(index, wrap(replacement, mode:))
    true
  end
end

#compare_by_identity? ⇒ Boolean

Returns Whether values are compared by identity.

Returns:

  • (Boolean) —

    Whether values are compared by identity.

See Also:



13
# File 'lib/farce/transaction/vector.rb', line 13

def compare_by_identity? = access { @object.compare_by_identity? }

#each {|value| ... } ⇒ self, Enumerator

Iterate over live entries, up to the length when enumeration starts. Changes can affect entries not yet visited. Indexes beyond the starting length are not visited. Each entry is read separately. The block runs without holding a collection lock.

Yields:

  • (value) —

    Called for each entry. Returns an Enumerator without a block.

Yield Parameters:

  • value (BasicObject) —

    The current value.

Yield Returns:

  • (void) —

    The result is ignored.

Returns:

  • (self, Enumerator)

See Also:



92
93
94
95
96
# File 'lib/farce/transaction/vector.rb', line 92

def each
  return enum_for(__method__) unless block_given?
  access { @working.snapshot.each { |value| yield unwrap_stored(value) } }
  self
end

#empty? ⇒ Boolean

Returns:

  • (Boolean)

See Also:

  • Abstract::Vector#empty?


38
# File 'lib/farce/transaction/vector.rb', line 38

def empty? = size.zero?

#get(index) ⇒ BasicObject?

Read an index after acquiring atomic-update access.

Parameters:

  • index (Integer) —

    The index. Negative indexes count from the end.

  • timeout (Numeric, nil) —

    The maximum wait in seconds. Nil waits indefinitely.

Returns:

  • (BasicObject, nil) —

    The value, or nil if absent or timed out.

See Also:



30
# File 'lib/farce/transaction/vector.rb', line 30

def get(index) = self[index]

#pop(count = UNDEFINED) ⇒ BasicObject, ...

Remove and return the last value, or a Vector of the last count values, atomically. This does not wait for an empty vector to become nonempty.

Parameters:

  • count (Integer) (defaults to: UNDEFINED) —

    The maximum number of values. Omit to return one value.

  • timeout (Numeric, nil) —

    The maximum wait in seconds. Nil waits indefinitely.

Returns:

  • (BasicObject, Vector, nil) —

    Removed values, or nil if empty without a count or timed out.

See Also:



79
80
81
# File 'lib/farce/transaction/vector.rb', line 79

def pop(count = UNDEFINED)
  write { count.equal?(UNDEFINED) ? unwrap_stored(@working.pop) : pop_values(count) }
end

#push(value = UNDEFINED, *rest, mode: nil) ⇒ self, false

Append values atomically. Calls with one value use the scalar backend path.

Parameters:

  • value (BasicObject) (defaults to: UNDEFINED) —

    The first value. Omit to leave contents unchanged.

  • rest (Array<BasicObject>) —

    Additional values to append.

  • timeout (Numeric, nil) —

    The maximum wait in seconds. Nil waits indefinitely.

Returns:

  • (self, false) —

    Self on success, or false on timeout.

See Also:



64
65
66
67
68
69
70
71
72
73
# File 'lib/farce/transaction/vector.rb', line 64

def push(value = UNDEFINED, *rest, mode: nil)
  write do
    if rest.empty? && !value.equal?(UNDEFINED)
      @working.push(wrap(value, mode:))
    else
      push_values(value.equal?(UNDEFINED) ? rest : [value, *rest], mode:)
    end
  end
  self
end

#shareable_values? ⇒ Boolean

Returns Whether stored values must be Ractor-shareable.

Returns:

  • (Boolean) —

    Whether stored values must be Ractor-shareable.

See Also:



17
# File 'lib/farce/transaction/vector.rb', line 17

def shareable_values? = access { @object.shareable_values? }

#size ⇒ Integer

Returns The number of slots, including nil slots.

Returns:

  • (Integer) —

    The number of slots, including nil slots.

See Also:



34
# File 'lib/farce/transaction/vector.rb', line 34

def size = access { @working.size }

#store(index, value, mode: nil) ⇒ BasicObject, false

Store a value after acquiring atomic-update access.

Parameters:

  • index (Integer) —

    The index. Negative indexes count from the end.

  • value (BasicObject) —

    The value to store.

  • timeout (Numeric, nil) —

    The maximum wait in seconds. Nil waits indefinitely.

Returns:

  • (BasicObject, false) —

    The value, or false on timeout.

See Also:



52
53
54
# File 'lib/farce/transaction/vector.rb', line 52

def store(index, value, mode: nil)
  write { unwrap_stored(@working.store(index, wrap(value, mode:))) }
end

#store_if_absent(index, mode: nil) { ... } ⇒ BasicObject?

Compute and store a value only when the index is absent or contains nil.

Parameters:

  • index (Integer) —

    The index. Negative indexes count from the end.

  • timeout (Numeric, nil) —

    The maximum wait in seconds. Nil waits indefinitely.

Yields:

  • Called without arguments to compute a value when the slot is absent or nil.

Yield Returns:

  • (BasicObject) —

    The value to store.

Returns:

  • (BasicObject, nil) —

    The existing or computed value, or nil on timeout.

See Also:



107
108
109
110
# File 'lib/farce/transaction/vector.rb', line 107

def store_if_absent(index, mode: nil)
  require_block!(block_given?)
  write { unwrap_stored(@working.store_if_absent(index) { wrap(yield, mode:) }) }
end

#swap(index, value, mode: nil) ⇒ BasicObject?

Replace an index and return its previous value, growing the vector if necessary.

Parameters:

  • index (Integer) —

    The index. Negative indexes count from the end.

  • replacement (BasicObject) —

    The new value.

  • timeout (Numeric, nil) —

    The maximum wait in seconds. Nil waits indefinitely.

Returns:

  • (BasicObject, nil) —

    The previous value, or nil if absent or timed out.

See Also:



58
59
60
# File 'lib/farce/transaction/vector.rb', line 58

def swap(index, value, mode: nil)
  write { unwrap_stored(@working.swap(index, wrap(value, mode:))) }
end

#update(index, mode: nil) {|value| ... } ⇒ BasicObject?

Atomically replace an index with the block result, growing the vector if necessary.

Parameters:

  • index (Integer) —

    The index. Negative indexes count from the end.

  • timeout (Numeric, nil) —

    The maximum wait in seconds. Nil waits indefinitely.

Yields:

  • (value) —

    Compute the replacement while holding atomic-update access.

Yield Parameters:

  • value (BasicObject, nil) —

    The current value, or nil if absent.

Yield Returns:

  • (BasicObject) —

    The replacement value.

Returns:

  • (BasicObject, nil) —

    The replacement value, or nil on timeout.

See Also:



100
101
102
103
# File 'lib/farce/transaction/vector.rb', line 100

def update(index, mode: nil)
  require_block!(block_given?)
  write { unwrap_stored(@working.update(index) { |value| wrap(yield(unwrap_stored(value)), mode:) }) }
end

#upsert(index, initial, mode: nil) {|value| ... } ⇒ BasicObject?

Store initial for an absent or nil index, otherwise replace it with the block result.

Parameters:

  • index (Integer) —

    The index. Negative indexes count from the end.

  • initial (BasicObject) —

    The value to store when the slot is absent or nil.

  • timeout (Numeric, nil) —

    The maximum wait in seconds. Nil waits indefinitely.

Yields:

  • (value) —

    Compute a replacement for an existing non-nil entry.

Yield Parameters:

  • value (BasicObject) —

    The current non-nil value.

Yield Returns:

  • (BasicObject) —

    The replacement value.

Returns:

  • (BasicObject, nil) —

    The stored value, or nil on timeout.

See Also:



114
115
116
117
118
119
120
121
# File 'lib/farce/transaction/vector.rb', line 114

def upsert(index, initial, mode: nil)
  require_block!(block_given?)
  write do
    unwrap_stored(@working.upsert(index, wrap(initial, mode:)) do |value|
      wrap(yield(unwrap_stored(value)), mode:)
    end)
  end
end