Replaced Ring Buffer with Array queue in AlertQueueManager class

In the AlertQueueManager class of the NETRAVE project, we made a
significant change to improve code simplicity, efficiency, and maintainability.
We replaced the previously used Ring Buffer with a standard Array queue for
 managing the queue of alerts. This change simplifies the code structure and
 improves the efficiency of queue management. As a result of this change, the
 Ring Buffer file, which is no longer needed, was also removed from the project.

 I would also like to thank Havenwood, Lapizistik, Sampersand, and Crimson
 from the Ruby discord in helping me determine the best data structure to use
 and helping me generally expand my deeper knowledge of Ruby
This commit is contained in:
VetheonGames 2023-07-06 09:08:39 -06:00
parent e50eac31b2
commit 7e17bd6e2d
2 changed files with 18 additions and 56 deletions

View File

@ -1,45 +1,47 @@
# frozen_string_literal: true
require_relative 'ring_buffer'
# Class for managing the queues for alerts
require_relative 'alert'
require_relative 'logg_man'
# Class for managing the queue of alerts. This class also manages a little bit of concurrency
# We use mutex for sync so we don't break Curses, as Curses isn't thread safe
class AlertQueueManager
SHUTDOWN_SIGNAL = 'shutdown'
def initialize(logger, size = 2 * 1024 * 1024) # rubocop:disable Metrics/MethodLength
def initialize(logger) # rubocop:disable Metrics/MethodLength
@loggman = logger
@queue = RingBuffer.new(@loggman, size)
@alert_queue = []
@shutdown = false
# Start a thread that continuously checks the queue and displays alerts
@worker_thread = Thread.new do
loop do
break if @shutdown && @queue.empty?
if @queue.empty?
if @alert_queue.empty?
sleep(0.1) # Sleep for 100 milliseconds
next
end
alert = @queue.pop # This will block until there's an alert in the queue
next if alert.nil?
alert = pop_alert
break if alert.message == SHUTDOWN_SIGNAL
alert.display
sleep(4.5)
alert.clear
end
end
end
def enqueue_alert(alert)
return if @shutdown
@alert_queue << alert
end
@queue.push(alert)
def pop_alert
@alert_queue.shift
end
def shutdown
@shutdown = true
enqueue_alert(Alert.new(SHUTDOWN_SIGNAL, :info))
@shutdown = true
end
def join_worker
@worker_thread.join if @shutdown
end
end

View File

@ -1,40 +0,0 @@
# frozen_string_literal: true
# Since the Standard Ruby library doesn't come with a Ring Buffer implementation, we need to make our own.
# this class creates a simple and rudementary implementation of a Ring Buffer for us to use.
class RingBuffer
def initialize(logger, size)
@loggman = logger
@size = size
@buffer = Array.new(size)
@start = 0
@end = 0
end
def push(element)
@loggman.log_warn('Attempted to push to a full buffer. Overwriting old data.') if full?
@buffer[@end] = element
@end = (@end + 1) % @size
@start = (@start + 1) % @size if @end == @start
end
def pop
if empty?
@loggman.log_warn('Attempted to pop from an empty buffer. Returning nil.')
return nil
end
element = @buffer[@start]
@start = (@start + 1) % @size
element
end
def empty?
@start == @end
end
def full?
(@end + 1) % @size == @start
end
end