class Pluggaloid::Event

Constants

Lock

Attributes

filter_another_thread[RW]
vm[RW]
options[RW]

オプション。以下のキーを持つHash

:prototype

引数の数と型。Arrayで、type_strictが解釈できる条件を設定する

:priority

Delayerの優先順位

Public Class Methods

new(*args) click to toggle source
Calls superclass method
# File lib/pluggaloid/event.rb, line 15
def initialize(*args)
  super
  @options = {}
  @listeners = [].freeze
  @filters = [].freeze
  @subscribers = Hash.new { |h, k| h[k] = [] }
  @stream_generators = Hash.new { |h, k| h[k] = Set.new }
end

Private Class Methods

__clear_aF4e__()
Alias for: clear!
clear!() click to toggle source
# File lib/pluggaloid/event.rb, line 249
def clear!
  @filter_another_thread = false
  __clear_aF4e__()
end
Also aliased as: __clear_aF4e__

Public Instance Methods

add_filter(event_filter) click to toggle source

イベントフィルタを追加する

Args

event_filter

イベントフィルタ(Filter)

Return

self

# File lib/pluggaloid/event.rb, line 154
def add_filter(event_filter)
  unless event_filter.is_a? Pluggaloid::Filter
    raise Pluggaloid::ArgumentError, "First argument must be Pluggaloid::Filter, but given #{event_filter.class}." end
  @filters = [*@filters, event_filter].freeze
  self
end
add_listener(listener) click to toggle source
# File lib/pluggaloid/event.rb, line 83
def add_listener(listener)
  case listener
  when Pluggaloid::Listener
    Lock.synchronize do
      if @listeners.map(&:slug).include?(listener.slug)
        raise Pluggaloid::DuplicateListenerSlugError, "Listener slug #{listener.slug} already exists."
      end
      @listeners = [*@listeners, listener].freeze
    end
    @stream_generators.values.each do |generators|
      generators.each(&:on_subscribed)
    end
  when Pluggaloid::Subscriber
    accepted_hash = listener.accepted_hash
    Lock.synchronize do
      @subscribers[accepted_hash] << listener
    end
    @stream_generators.fetch(accepted_hash, nil)&.each(&:on_subscribed)
  else
    raise Pluggaloid::ArgumentError, "First argument must be Pluggaloid::Listener or Pluggaloid::Subscriber, but given #{listener.class}."
  end
  self
end
argument_hash(args, exclude_index) click to toggle source
# File lib/pluggaloid/event.rb, line 175
def argument_hash(args, exclude_index)
  args.each_with_index.map do |item, i|
    if i != exclude_index
      item.hash
    end
  end.compact.freeze
end
call(*args) click to toggle source

イベントを引数 args で発生させる

Args

*args

イベントの引数

Return

Delayerか、イベントを待ち受けているリスナがない場合はnil

# File lib/pluggaloid/event.rb, line 57
def call(*args)
  if self.class.filter_another_thread
    if @filters.empty?
      vm.Delayer.new(*Array(priority)) do
      call_all_listeners(args) end
    else
      Thread.new do
        filtered_args = filtering(*args)
        if filtered_args.is_a? Array
          vm.Delayer.new(*Array(priority)) do
            call_all_listeners(filtered_args) end end end end
  else
    vm.Delayer.new(*Array(priority)) do
      args = filtering(*args) if not @filters.empty?
      call_all_listeners(args) if args.is_a? Array end end end
collect(*args) click to toggle source

defeventで定義されたprototype引数に Pluggaloid::COLLECT を含むイベントに対して使える。 フィルタの Pluggaloid::COLLECT 引数に空の配列を渡して実行したあと、その配列を返す。

Args

*args

Pluggaloid::COLLECT 以外の引数のリスト

Return

Array

フィルタ実行結果

# File lib/pluggaloid/event.rb, line 203
def collect(*args)
  specified_index = args.index(Pluggaloid::COLLECT)
  specified_index&.yield_self(&args.method(:delete_at))
  insert_index = collect_index || specified_index
  if insert_index
    Enumerator.new do |yielder|
      cargs = args.dup
      cargs.insert(insert_index, yielder)
      filtering(*cargs)
    end
  else
    raise Pluggaloid::UndefinedCollectionIndexError, 'To call collect(), it must define prototype arguments include `Pluggaloid::COLLECT\'.'
  end
end
collect_index() click to toggle source
# File lib/pluggaloid/event.rb, line 190
def collect_index
  unless defined?(@collect_index)
    @collect_index = self.prototype&.index(Pluggaloid::COLLECT)
  end
  @collect_index
end
collection_add_event() click to toggle source
# File lib/pluggaloid/event.rb, line 223
def collection_add_event
  self.class['%{name}__add' % {name: name}]
end
collection_delete_event() click to toggle source
# File lib/pluggaloid/event.rb, line 227
def collection_delete_event
  self.class['%{name}__delete' % {name: name}]
end
defevent(new_options) click to toggle source

イベント event_name を宣言する

Args

new_options

イベントの定義

# File lib/pluggaloid/event.rb, line 31
def defevent(new_options)
  @options.merge!(new_options)
  if collect_index
    new_proto = self.prototype.dup
    new_proto[self.collect_index] = Pluggaloid::STREAM
    collection_add_event.defevent(prototype: new_proto)
    collection_delete_event.defevent(prototype: new_proto)
  end
  self
end
delete_filter(event_filter) click to toggle source

イベントフィルタを削除する

Args

event_filter

イベントフィルタ(EventFilter)

Return

self

# File lib/pluggaloid/event.rb, line 166
def delete_filter(event_filter)
  Lock.synchronize do
    @filters = @filters.dup
    @filters.delete(event_filter)
    @filters.freeze
  end
  self
end
delete_listener(listener) click to toggle source
# File lib/pluggaloid/event.rb, line 117
def delete_listener(listener)
  Lock.synchronize do
    @listeners = @listeners.dup
    @listeners.delete(listener)
    @listeners.freeze
  end
  self
end
delete_stream_generator(listener) click to toggle source
# File lib/pluggaloid/event.rb, line 138
def delete_stream_generator(listener)
  Lock.synchronize do
    ss = @stream_generators[listener.accepted_hash]
    ss.delete(listener)
    if ss.empty?
      @stream_generators.delete(listener.accepted_hash)
    end
  end
  self
end
delete_subscriber(listener) click to toggle source
# File lib/pluggaloid/event.rb, line 126
def delete_subscriber(listener)
  Lock.synchronize do
    ss = @subscribers[listener.accepted_hash]
    ss.delete(listener)
    if ss.empty?
      @subscribers.delete(listener.accepted_hash)
    end
  end
  @stream_generators.fetch(listener.accepted_hash, nil)&.each(&:on_unsubscribed)
  self
end
filtering(*args) click to toggle source

引数 args をフィルタリングした結果を返す

Args

*args

引数

Return

フィルタされた引数の配列

# File lib/pluggaloid/event.rb, line 78
def filtering(*args)
  catch(:filter_exit) {
    @filters.reduce(args){ |acm, event_filter|
      event_filter.filtering(*acm) } } end
priority() click to toggle source

イベントの優先順位を取得する

Return

プラグインの優先順位

# File lib/pluggaloid/event.rb, line 48
def priority
  if @options.has_key? :priority
    @options[:priority] end end
prototype() click to toggle source
# File lib/pluggaloid/event.rb, line 24
def prototype
  @options[:prototype]
end
register_stream_generator(stream_generator) click to toggle source
# File lib/pluggaloid/event.rb, line 218
def register_stream_generator(stream_generator)
  @stream_generators[stream_generator.accepted_hash] << stream_generator
  self
end
stream_index() click to toggle source
# File lib/pluggaloid/event.rb, line 183
def stream_index
  unless defined?(@stream_index)
    @stream_index = self.prototype&.index(Pluggaloid::STREAM)
  end
  @stream_index
end
subscribe?(*specs) click to toggle source

subscribe(_*specs_) で、ストリームの受信をしようとしているリスナが定義されていればtrueを返す。 on_* で通常のイベントリスナが登録されて居る場合は、 _*specs_ の内容に関わらず常にtrueを返す。

# File lib/pluggaloid/event.rb, line 109
def subscribe?(*specs)
  !@listeners.empty? || @subscribers.key?(argument_hash(specs, nil))
end
vm() click to toggle source
# File lib/pluggaloid/event.rb, line 42
def vm
  self.class.vm end

Private Instance Methods

call_all_listeners(args) click to toggle source
# File lib/pluggaloid/event.rb, line 232
def call_all_listeners(args)
  if stream_index
    @subscribers[argument_hash(args, stream_index)]&.each do |subscriber|
      subscriber.call(*args)
    end
  end
  catch(:plugin_exit) do
    @listeners.each do |listener|
      listener.call(*args)
    end
  end
end