Class: Orocos::Async::ObjectBase

Inherits:
Object
  • Object
show all
Defined in:
lib/orocos/async/object_base.rb

Defined Under Namespace

Modules: Periodic

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, event_loop) ⇒ ObjectBase

Returns a new instance of ObjectBase

Raises:

  • (ArgumentError)


173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# 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

Instance Attribute Details

#emitting(value, &block) ⇒ Object

sets @emitting to value for the time the given block is called



195
196
197
# File 'lib/orocos/async/object_base.rb', line 195

def emitting
  @emitting
end

#event_loopObject (readonly)

Returns the value of attribute event_loop



157
158
159
# File 'lib/orocos/async/object_base.rb', line 157

def event_loop
  @event_loop
end

#nameObject

Returns the value of attribute name



160
161
162
# File 'lib/orocos/async/object_base.rb', line 160

def name
  @name
end

#optionsObject (readonly)

Returns the value of attribute options



158
159
160
# File 'lib/orocos/async/object_base.rb', line 158

def options
  @options
end

#pending_addsArray<EventLoop,nil> (readonly)

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.

Returns:

  • (Array<EventLoop,nil>)


171
172
173
# File 'lib/orocos/async/object_base.rb', line 171

def pending_adds
  @pending_adds
end

Class Method Details

.define_event(name) ⇒ Object



119
120
121
# File 'lib/orocos/async/object_base.rb', line 119

def define_event(name)
    define_events(name)
end

.define_events(*names) ⇒ Object



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# 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

.event_namesObject



111
112
113
114
115
116
117
# File 'lib/orocos/async/object_base.rb', line 111

def event_names
    @event_names ||= if self != ObjectBase
                         superclass.event_names.dup
                     else
                         []
                     end
end

.valid_event?(name) ⇒ Boolean

Returns:

  • (Boolean)


144
145
146
# File 'lib/orocos/async/object_base.rb', line 144

def valid_event?(name)
    event_names.include?(name)
end

.validate_event(name) ⇒ Object



148
149
150
151
152
153
154
# 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

Instance Method Details

#add_listener(listener) ⇒ Object



275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
# 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

#disable_emitting(&block) ⇒ Object



202
203
204
# File 'lib/orocos/async/object_base.rb', line 202

def disable_emitting(&block)
    emitting(false,&block)
end

#event(event_name, *args, &block) ⇒ Object

calls all listener which are registered for the given event the next step



334
335
336
337
338
339
340
341
# 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

#event_namesObject



215
216
217
# File 'lib/orocos/async/object_base.rb', line 215

def event_names
    self.class.event_names
end

#invalidate_delegator!Object



190
191
192
# File 'lib/orocos/async/object_base.rb', line 190

def invalidate_delegator!
    @delegator_obj = DelegatorDummy.new self,@name,@event_loop
end

#listener?(listener) ⇒ Boolean

returns true if the listener is active

Returns:

  • (Boolean)


231
232
233
# File 'lib/orocos/async/object_base.rb', line 231

def listener?(listener)
    @listeners[listener.event].include? listener
end

#listeners(event) ⇒ Object

returns the listeners for the given event



236
237
238
239
# File 'lib/orocos/async/object_base.rb', line 236

def listeners(event)
    event = validate_event event
    @listeners[event]
end

#number_of_listeners(event) ⇒ Object

returns the number of listener for the given event



225
226
227
228
# File 'lib/orocos/async/object_base.rb', line 225

def number_of_listeners(event)
    event = validate_event event
    @listeners[event].size
end

#on_event(event, use_last_value = true, &block) ⇒ Object



219
220
221
222
# 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

#proxy_event(obj, *events) ⇒ Object

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



246
247
248
249
250
251
252
253
254
255
256
257
258
# 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

#reachable!(obj, options = Hash.new) ⇒ Object



363
364
365
366
# File 'lib/orocos/async/object_base.rb', line 363

def reachable!(obj,options = Hash.new)
    @delegator_obj = obj
    event :reachable if valid_delegator?
end

#reachable?(&block) ⇒ Boolean

TODO CODE BLOCK

Returns:

  • (Boolean)


359
360
361
# File 'lib/orocos/async/object_base.rb', line 359

def reachable?(&block)
    valid_delegator?
end

#really_add_listener(listener) ⇒ Object



293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
# 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

#remove_all_listenersObject



379
380
381
382
383
384
385
# 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

#remove_listener(listener) ⇒ Object



315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
# 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

#remove_proxy_event(obj, *events) ⇒ Object



260
261
262
263
264
265
266
267
268
269
270
271
272
273
# 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

#unreachable!(options = Hash.new) ⇒ Object



368
369
370
371
372
373
# File 'lib/orocos/async/object_base.rb', line 368

def unreachable!(options = Hash.new)
    if valid_delegator?
        invalidate_delegator!
        event :unreachable
    end
end

#valid_delegator?Boolean

Returns:

  • (Boolean)


375
376
377
# File 'lib/orocos/async/object_base.rb', line 375

def valid_delegator?
    !@delegator_obj.is_a? DelegatorDummy
end

#valid_event?(event) ⇒ Boolean

returns true if the event is known

Returns:

  • (Boolean)


207
208
209
# File 'lib/orocos/async/object_base.rb', line 207

def valid_event?(event)
    self.class.valid_event?(event)
end

#validate_event(event) ⇒ Object



211
212
213
# File 'lib/orocos/async/object_base.rb', line 211

def validate_event(event)
    self.class.validate_event(event)
end

#wait(timeout = 5.0) ⇒ Object

waits until object gets reachable raises Orocos::NotFound if the object was not reachable after the given time spawn



345
346
347
348
349
350
351
352
353
354
355
356
# 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