Class: Splib::PriorityQueue

Inherits:
Object
  • Object
show all
Defined in:
lib/splib/PriorityQueue.rb

Overview

This class provides some simple logic for item output. It is basically a priority based queue with some round robin thrown in to keep things interesting. This queue provides an easy way for many threads to populate it without drowning out each other. NOTE: Design help from the great Ryan “pizza_” Flynn

Instance Method Summary collapse

Constructor Details

#initialize(*args, &whocares) ⇒ PriorityQueue

args

config arguments

:raise_on_empty
whocares

lambda{|target| true||false}

Create a priority queue



18
19
20
21
22
23
24
# File 'lib/splib/PriorityQueue.rb', line 18

def initialize(*args, &whocares)
    @raise = args.include?(:raise_on_empty)
    @whocares = whocares
    @target_queues = {}
    @queues = {:PRIORITY => [], :NEW => [], :NORMAL => [], :WHOCARES => []}
    @lock = Splib::Monitor.new
end

Instance Method Details

#direct_queue(message) ⇒ Object Also known as: <<

item

item to queue

This will add item to the PRIORITY queue which gets sent before all other items.



54
55
56
57
58
59
60
61
62
# File 'lib/splib/PriorityQueue.rb', line 54

def direct_queue(message)
    @lock.synchronize do
        @target_queues[:internal_prio] = [] unless @target_queues[:internal_prio]
        @target_queues[:internal_prio] << message
        add_queue(:PRIORITY, @target_queues[:internal_prio])
        @lock.signal
    end
    message
end

#empty?Boolean

Returns true if queue is empty

Returns:

  • (Boolean)


95
96
97
# File 'lib/splib/PriorityQueue.rb', line 95

def empty?
    @lock.synchronize{@target_queues.values.find{|n|!n.empty?}.nil?}
end

#popObject

raise_e

raise an exception on empty

Returns the next message to send. This method decides what message to send based on the priority of the message. It will throw an Exceptions::EmptyQueue when there are no messages left.



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/splib/PriorityQueue.rb', line 69

def pop
    m = nil
    @lock.synchronize do
        [:PRIORITY, :NEW, :NORMAL, :WHOCARES].each do |k|
            unless(@queues[k].empty?)
                q = @queues[k].shift
                unless(q.empty?)
                    m = q.shift
                    add_queue(k, q) unless(q.empty?)
                    break
                end
            end
        end
    end
    unless(m)
        if(@raise)
            raise EmptyQueue.new('Queue is currently empty')
        else
            @lock.wait_while{ empty? }
            m = pop
        end
    end
    m
end

#prioritized_queue(target, item) ⇒ Object Also known as: push

target

target queue

item

item to queue

This prioritizes output to help reduce lag when lots of output is being sent to another target. This will automatically decide how to queue the item based on the target

Raises:

  • (NameError)


31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/splib/PriorityQueue.rb', line 31

def prioritized_queue(target, item)
    raise NameError.new('The target :internal_prio is a restricted target') if target == :internal_prio
    @lock.synchronize do
        @target_queues[target] = [] unless @target_queues[target]
        if(@whocares && @whocares.call(target))
            @target_queues[target] << item
            add_queue(:WHOCARES, @target_queues[target])
        else
            @target_queues[target] << item
            if(@target_queues[target].size < 2)
                add_queue(:NEW, @target_queues[target])
            else
                add_queue(:NORMAL, @target_queues[target])
            end
        end
        @lock.signal
    end
    item
end