Class: Syndi::Events

Inherits:
Object
  • Object
show all
Defined in:
lib/syndi/events.rb

Overview

A simple event management system, designed particularly for Syndi.

Defined Under Namespace

Classes: Listener

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeEvents

Returns a new instance of Events.



16
17
18
# File 'lib/syndi/events.rb', line 16

def initialize
  @events = Hash.new
end

Instance Attribute Details

#eventsHash{Symbol => Array<Syndi::Events::Listener>} (readonly)

Returns The collection of events and associated listeners.

Returns:



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/syndi/events.rb', line 12

class Events

  attr_reader :events

  def initialize
    @events = Hash.new
  end

  # Create a new listener on a given +event+, which will have the given
  # block attached and executed upon the event's occurrence.
  #
  # @param [Symbol] event The event which to await.
  # @param [Integer] priority The priority this listener should have in the hook
  #    execution procedure. Must be 1-5 with 1 being of utmost priority.
  #
  # @yield [...] The parameters passed when the event was broadcasted. This varies
  #   by event. See the official event reference for Syndi events.
  #
  # @return [Syndi::Events::Listener] The listener.
  def on event, priority = 3, &prc
    @events[event] ||= Array.new

    if priority < 1 || priority > 5
      raise ArgumentError, "invalid event priority specified"
    end

    hook = Listener.new self, event, priority, prc
    @events[event] << hook
    hook
  end

  # This will broadcast the given +event+, executing each listener and passing
  # to it the parameters supplied here, respecting priority and operating in a
  # thread.
  #
  # @param [Symbol] event
  # @param [...] parameters The arguments to be passed to each listener.
  def emit event, *parameters
    if @events[event]

      # collect the listeners with respect to priority
      one, two, three, four, five = gather @events[event]

      Syndi.log.verbose "event *#{event}* is being broadcasted on #{self}", VNOISY

      # spawn a thread and perform the executions
      Thread.new do
        begin
          # cease if status ever becomes false/nil
          status = true
          
          one.each   { |code| status = code.call *parameters if status }
          two.each   { |code| status = code.call *parameters if status }
          three.each { |code| status = code.call *parameters if status }
          four.each  { |code| status = code.call *parameters if status }
          five.each  { |code| status = code.call *parameters if status }
        rescue => e
          # catch thread errors
          Syndi.log.error "A listener to a broadcast of #{event} on #{self} caused an exception to rise (#{e})", true
        end
      end

    end
  end

  def inspect
    "<#Syndi::Events: obj_id=#{object_id} event_count=#{@events.length}>"
  end
  alias_method :to_s, :inspect

  private

  # Gather hooks.
  def gather list
    [list.collect { |hook| (hook.priority == 1 ? hook : nil) }.compact,
     list.collect { |hook| (hook.priority == 2 ? hook : nil) }.compact,
     list.collect { |hook| (hook.priority == 3 ? hook : nil) }.compact,
     list.collect { |hook| (hook.priority == 4 ? hook : nil) }.compact,
     list.collect { |hook| (hook.priority == 5 ? hook : nil) }.compact]
  end

  public

  # A class which represents a listener.
  class Listener
    attr_reader :event, :priority, :code

    # Spawn a new listener object.
    def initialize sys, event, priority, prc
      @sys      = sys
      @event    = event
      @priority = priority
      @code     = prc

      Syndi.log.verbose "new listener spawned and attached to #{event}: #{self}", VNOISY
    end

    # Terminate this object.
    def deaf
      @sys.events[event].delete self
    end

    # Execute this listener.
    def call *args
      @code.call *args
    end

    def inspect
      "<#Syndi::Events::Listener: sys=#@sys event=#@event priority=#@priority>"
    end
    alias_method :to_s, :inspect

  end

end

Instance Method Details

#emit(event, *parameters) ⇒ Object

This will broadcast the given +event+, executing each listener and passing to it the parameters supplied here, respecting priority and operating in a thread.

Parameters:

  • event (Symbol)
  • parameters (...)

    The arguments to be passed to each listener.



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/syndi/events.rb', line 49

def emit event, *parameters
  if @events[event]

    # collect the listeners with respect to priority
    one, two, three, four, five = gather @events[event]

    Syndi.log.verbose "event *#{event}* is being broadcasted on #{self}", VNOISY

    # spawn a thread and perform the executions
    Thread.new do
      begin
        # cease if status ever becomes false/nil
        status = true
        
        one.each   { |code| status = code.call *parameters if status }
        two.each   { |code| status = code.call *parameters if status }
        three.each { |code| status = code.call *parameters if status }
        four.each  { |code| status = code.call *parameters if status }
        five.each  { |code| status = code.call *parameters if status }
      rescue => e
        # catch thread errors
        Syndi.log.error "A listener to a broadcast of #{event} on #{self} caused an exception to rise (#{e})", true
      end
    end

  end
end

#gather(list) ⇒ Object (private)

Gather hooks.



85
86
87
88
89
90
91
# File 'lib/syndi/events.rb', line 85

def gather list
  [list.collect { |hook| (hook.priority == 1 ? hook : nil) }.compact,
   list.collect { |hook| (hook.priority == 2 ? hook : nil) }.compact,
   list.collect { |hook| (hook.priority == 3 ? hook : nil) }.compact,
   list.collect { |hook| (hook.priority == 4 ? hook : nil) }.compact,
   list.collect { |hook| (hook.priority == 5 ? hook : nil) }.compact]
end

#inspectObject Also known as: to_s



77
78
79
# File 'lib/syndi/events.rb', line 77

def inspect
  "<#Syndi::Events: obj_id=#{object_id} event_count=#{@events.length}>"
end

#on(event, priority = 3) {|...| ... } ⇒ Syndi::Events::Listener

Create a new listener on a given +event+, which will have the given block attached and executed upon the event's occurrence.

Parameters:

  • event (Symbol)

    The event which to await.

  • priority (Integer) (defaults to: 3)

    The priority this listener should have in the hook execution procedure. Must be 1-5 with 1 being of utmost priority.

Yields:

  • (...)

    The parameters passed when the event was broadcasted. This varies by event. See the official event reference for Syndi events.

Returns:



31
32
33
34
35
36
37
38
39
40
41
# File 'lib/syndi/events.rb', line 31

def on event, priority = 3, &prc
  @events[event] ||= Array.new

  if priority < 1 || priority > 5
    raise ArgumentError, "invalid event priority specified"
  end

  hook = Listener.new self, event, priority, prc
  @events[event] << hook
  hook
end