class SamsaraSDK::RingBuffer

Thread-safe ring-buffer data queue tailored for Samsara Client.

Public Class Methods

new(size) click to toggle source

initialize.

@param size [Integer] Storage size.

# File lib/samsara_sdk/ring_buffer.rb, line 8
def initialize(size)
  @size = size
  @low = -1
  @high = -1
  @buffer = Array.new(size)
  @mutex = Mutex.new
end

Public Instance Methods

<<(value)
Alias for: push
count() click to toggle source

Get current number of items in buffer.

@return [Integer] number of pushed elements.

# File lib/samsara_sdk/ring_buffer.rb, line 19
def count
  @high - @low
end
empty?() click to toggle source

Is buffer empty?

@return [Boolean] Empty or not.

# File lib/samsara_sdk/ring_buffer.rb, line 33
def empty?
  count.zero?
end
flush() { |data| ... } click to toggle source

Extract all existing elements out of buffer.

@yield [data] Block that processes data and returns success of the processing. @yieldparam [Array<Object>] data Buffer data. @yieldreturn [Boolean] Result of data processing. True if success, false otherwise.

@return [Array<Object>] All buffer's elements in FIFO order.

# File lib/samsara_sdk/ring_buffer.rb, line 58
def flush
  data, at_mark = take_snapshot
  success = block_given? ? yield(data) : TRUE
  delete at_mark if success
  data
end
full?() click to toggle source

Is buffer full?

@return [Boolean] Full or not.

# File lib/samsara_sdk/ring_buffer.rb, line 26
def full?
  count == @size
end
push(value) click to toggle source

Puts element into buffer.

@return [Object] Element that has been put into buffer.

# File lib/samsara_sdk/ring_buffer.rb, line 40
def push(value)
  @mutex.synchronize do
    return if @size.zero?
    @high += 1
    @low += 1 if count > @size
    @buffer[high_position] = value
    value
  end
end
Also aliased as: <<

Private Instance Methods

calculate_position(pointer) click to toggle source

Helper-method for calculating position in a circle.

@return [Integer] position of a given pointer.

# File lib/samsara_sdk/ring_buffer.rb, line 70
def calculate_position(pointer)
  @size.nonzero? ? pointer.remainder(@size) : -1
end
delete(mark) click to toggle source

Removes chunk of elements that present in a snapshot out of buffer. Detects if the last consumed element has been overridden by new pushes.

@param mark [Integer] high attribute that represents high-water-mark of a snapshot.

# File lib/samsara_sdk/ring_buffer.rb, line 122
def delete(mark)
  @mutex.synchronize do
    @low = [@low, mark].max
    @high = [@high, mark].max
  end
end
high_position() click to toggle source

Get array-position of the element that was last added. Must be used within a synced mutex.

@return [Integer] position.

# File lib/samsara_sdk/ring_buffer.rb, line 78
def high_position
  calculate_position @high
end
low_position() click to toggle source

Get array-position of the element that was last consumed. Must be used within a synced mutex.

@return [Integer] position.

# File lib/samsara_sdk/ring_buffer.rb, line 86
def low_position
  calculate_position @low
end
take_snapshot() click to toggle source

Make a snapshot of the current buffer at a given moment in FIFO order. Notes: It could be implemented just by iterating through @buffer and taking elements between @low and @high; but it's not as efficient as Ruby native array manipulations. So we stick to manipulating indices and handling different cases to get FIFO.

@return [Array<Object>] actual elements in FIFO order, @return [Integer] High-water-mark that snapshot was taken at.

# File lib/samsara_sdk/ring_buffer.rb, line 99
def take_snapshot
  @mutex.synchronize do
    i = high_position
    j = low_position + 1

    data = if empty?
             []
           elsif @low == -1
             @buffer.compact
           elsif @high < @size # array is not filled completely
             @buffer[j..i]
           else
             @buffer[j..-1] + @buffer[0..i]
           end

    return data, @high
  end
end