class Orocos::Async::ObjectBase
Attributes
Queue of listener that are going to be added by callbacks registered in the event loop. This is filled and processed by add_listener and remove_listener
Some entries might be nil if remove_listener has been called before the event loop processed the addition callbacks.
@return [Array<EventLoop,nil>]
Public Class Methods
# File lib/orocos/async/object_base.rb, line 119 def define_event(name) define_events(name) end
# File lib/orocos/async/object_base.rb, line 123 def define_events(*names) names.flatten! names.each do |n| raise "Cannot add event #{n}. It is already added" if event_names.include? n event_names << n str = %Q{ def on_#{n}(use_last_value = true,&block) on_event #{n.inspect},use_last_value,&block end def once_on_#{n}(use_last_value = true,&block) l = on_event #{n.inspect},use_last_value do |*args| block.call(*args) l.stop end end def emit_#{n}(*args) event #{n.inspect},*args end } class_eval(str) end end
# File lib/orocos/async/object_base.rb, line 111 def event_names @event_names ||= if self != ObjectBase superclass.event_names.dup else [] end end
# File lib/orocos/async/object_base.rb, line 173 def initialize(name,event_loop) raise ArgumentError, "no name was given" if !name @listeners ||= Hash.new{ |hash,key| hash[key] = []} @proxy_listeners ||= Hash.new{|hash,key| hash[key] = Hash.new} @name ||= name @event_loop ||= event_loop @options ||= Hash.new @emitting = true @pending_adds = Array.new invalidate_delegator! on_error do |e| if e.kind_of?(Orocos::ComError) unreachable!(:error => e) end end end
# File lib/orocos/async/object_base.rb, line 144 def valid_event?(name) event_names.include?(name) end
# File lib/orocos/async/object_base.rb, line 148 def validate_event(name) name = name.to_sym if !valid_event?(name) raise "event #{name} is not emitted by #{self}. The following events are emitted #{event_names.join(", ")}" end name end
Public Instance Methods
# File lib/orocos/async/object_base.rb, line 275 def add_listener(listener) event = validate_event listener.event return listener if pending_adds.include? listener pending_adds << listener event_loop.once do expected = pending_adds.shift # 'expected' is nil if the listener has been removed before this # block got processed if expected if expected != listener raise RuntimeError, "internal error in #{self}#add_listener: pending addition and expected addition mismatch" end really_add_listener(listener) end end listener end
# File lib/orocos/async/object_base.rb, line 202 def disable_emitting(&block) emitting(false,&block) end
calls all listener which are registered for the given event the next step
# File lib/orocos/async/object_base.rb, line 334 def event(event_name,*args,&block) validate_event event_name return unless @emitting @event_loop.once do process_event event_name,*args,&block end self end
# File lib/orocos/async/object_base.rb, line 215 def event_names self.class.event_names end
# File lib/orocos/async/object_base.rb, line 190 def invalidate_delegator! @delegator_obj = DelegatorDummy.new self,@name,@event_loop end
returns true if the listener is active
# File lib/orocos/async/object_base.rb, line 231 def listener?(listener) @listeners[listener.event].include? listener end
returns the listeners for the given event
# File lib/orocos/async/object_base.rb, line 236 def listeners(event) event = validate_event event @listeners[event] end
returns the number of listener for the given event
# File lib/orocos/async/object_base.rb, line 225 def number_of_listeners(event) event = validate_event event @listeners[event].size end
# File lib/orocos/async/object_base.rb, line 219 def on_event(event,use_last_value=true,&block) event = validate_event event EventListener.new(self,event,use_last_value,&block).start end
adds a listener to obj and proxies event like it would be emitted from self
if no listener is registererd to event it also removes the listener from obj
# File lib/orocos/async/object_base.rb, line 246 def proxy_event(obj,*events) return if obj == self events = events.flatten events.each do |e| if existing = @proxy_listeners[obj].delete(e) existing.stop end l = @proxy_listeners[obj][e] = EventListener.new(obj,e,true) do |*val| process_event e,*val end l.start if number_of_listeners(e) > 0 end end
# File lib/orocos/async/object_base.rb, line 363 def reachable!(obj,options = Hash.new) @delegator_obj = obj event :reachable if valid_delegator? end
TODO CODE BLOCK
# File lib/orocos/async/object_base.rb, line 359 def reachable?(&block) valid_delegator? end
# File lib/orocos/async/object_base.rb, line 293 def really_add_listener(listener) if listener.use_last_value? if listener.event == :reachable listener.call if valid_delegator? elsif listener.event == :unreachable listener.call if !valid_delegator? end end @proxy_listeners.each do |obj,listeners| if l = listeners[listener.event] if listener.use_last_value? && !listener.last_args # replay last value if requested obj.really_add_listener(listener) obj.remove_listener(listener) end l.start(false) unless l.listening? end end @listeners[listener.event] << listener unless @listeners[listener.event].include?(listener) listener end
# File lib/orocos/async/object_base.rb, line 379 def remove_all_listeners !@listeners.each do |event,listeners| while !listeners.empty? remove_listener listeners.first end end end
# File lib/orocos/async/object_base.rb, line 315 def remove_listener(listener) if idx = pending_adds.index(listener) pending_adds[idx] = nil end @listeners[listener.event].delete listener # Check whether the only listeners left are proxy listeners. If they # are, remove them if number_of_listeners(listener.event) == 0 @proxy_listeners.each do |obj, listeners| if l = listeners[listener.event] obj.remove_listener(l) end end end end
# File lib/orocos/async/object_base.rb, line 260 def remove_proxy_event(obj,*events) return if obj == self events = events.flatten if events.empty? remove_proxy_event(obj,@proxy_listeners[obj].keys) @proxy_listeners.delete(obj) else events.each do |e| if listener = @proxy_listeners[obj].delete(e) listener.stop end end end end
# File lib/orocos/async/object_base.rb, line 368 def unreachable!(options = Hash.new) if valid_delegator? invalidate_delegator! event :unreachable end end
# File lib/orocos/async/object_base.rb, line 375 def valid_delegator? !@delegator_obj.is_a? DelegatorDummy end
returns true if the event is known
# File lib/orocos/async/object_base.rb, line 207 def valid_event?(event) self.class.valid_event?(event) end
# File lib/orocos/async/object_base.rb, line 211 def validate_event(event) self.class.validate_event(event) end
waits until object gets reachable raises Orocos::NotFound if the object was not reachable after the given time spawn
# File lib/orocos/async/object_base.rb, line 345 def wait(timeout = 5.0) time = Time.now @event_loop.wait_for do if timeout && timeout <= Time.now-time Utilrb::EventLoop.cleanup_backtrace do raise Orocos::NotFound,"#{self.class}: #{respond_to?(:full_name) ? full_name : name} is not reachable after #{timeout} seconds" end end reachable? end self end