112 lines
1.8 KiB
Ruby
112 lines
1.8 KiB
Ruby
|
# frozen_string_literal: true
|
||
|
|
||
|
require "monitor"
|
||
|
|
||
|
module WorkQueue
|
||
|
class WorkQueueFull < StandardError
|
||
|
end
|
||
|
|
||
|
class ThreadSafeWrapper
|
||
|
include MonitorMixin
|
||
|
|
||
|
def initialize(queue)
|
||
|
mon_initialize
|
||
|
|
||
|
@queue = queue
|
||
|
@has_items = new_cond
|
||
|
end
|
||
|
|
||
|
def push(task, force:)
|
||
|
synchronize do
|
||
|
previously_empty = @queue.empty?
|
||
|
@queue.push(task, force: force)
|
||
|
|
||
|
@has_items.signal if previously_empty
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def shift(block:)
|
||
|
synchronize do
|
||
|
loop do
|
||
|
if task = @queue.shift
|
||
|
break task
|
||
|
elsif block
|
||
|
@has_items.wait
|
||
|
else
|
||
|
break nil
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def empty?
|
||
|
synchronize { @queue.empty? }
|
||
|
end
|
||
|
|
||
|
def size
|
||
|
synchronize { @queue.size }
|
||
|
end
|
||
|
end
|
||
|
|
||
|
class FairQueue
|
||
|
attr_reader :size
|
||
|
|
||
|
def initialize(limit, &blk)
|
||
|
@limit = limit
|
||
|
@size = 0
|
||
|
@elements = Hash.new { |h, k| h[k] = blk.call }
|
||
|
end
|
||
|
|
||
|
def push(task, force:)
|
||
|
raise WorkQueueFull if !force && @size >= @limit
|
||
|
key, task = task.values_at(:key, :task)
|
||
|
@elements[key].push(task, force: force)
|
||
|
@size += 1
|
||
|
nil
|
||
|
end
|
||
|
|
||
|
def shift
|
||
|
unless @elements.empty?
|
||
|
key, queue = @elements.shift
|
||
|
|
||
|
task = queue.shift
|
||
|
|
||
|
@elements[key] = queue unless queue.empty?
|
||
|
|
||
|
@size -= 1
|
||
|
|
||
|
{ key: key, task: task }
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def empty?
|
||
|
@elements.empty?
|
||
|
end
|
||
|
end
|
||
|
|
||
|
class BoundedQueue
|
||
|
def initialize(limit)
|
||
|
@limit = limit
|
||
|
@elements = []
|
||
|
end
|
||
|
|
||
|
def push(task, force:)
|
||
|
raise WorkQueueFull if !force && @elements.size >= @limit
|
||
|
@elements << task
|
||
|
nil
|
||
|
end
|
||
|
|
||
|
def shift
|
||
|
@elements.shift
|
||
|
end
|
||
|
|
||
|
def empty?
|
||
|
@elements.empty?
|
||
|
end
|
||
|
|
||
|
def size
|
||
|
@elements.size
|
||
|
end
|
||
|
end
|
||
|
end
|