class SamsaraSDK::RingBuffer
Thread-safe ring-buffer data queue tailored for Samsara Client
.
Public Class Methods
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
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
Is buffer empty?
@return [Boolean] Empty or not.
# File lib/samsara_sdk/ring_buffer.rb, line 33 def empty? count.zero? end
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
Is buffer full?
@return [Boolean] Full or not.
# File lib/samsara_sdk/ring_buffer.rb, line 26 def full? count == @size end
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
Private Instance Methods
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
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
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
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
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