Class: Roby::AndGenerator

Inherits:
EventGenerator show all
Defined in:
lib/roby/and_generator.rb

Overview

Combine event generators using an AND. The generator will emit once all its source events have emitted, and become unreachable if any of its source events have become unreachable.

For instance,

a = task1.start_event
b = task2.start_event
(a & b) # will emit when both tasks have started

And events will emit only once, unless #reset is called:

a = task1.intermediate_event
b = task2.intermediate_event
and_ev = (a & b)

a.intermediate_event!
b.intermediate_event! # and_ev emits here
a.intermediate_event!
b.intermediate_event! # and_ev does *not* emit

and_ev.reset
a.intermediate_event!
b.intermediate_event! # and_ev emits here

The AndGenerator tracks its sources via the signalling relations, so

and_ev << c.intermediate_event

is equivalent to

c.intermediate_event.add_signal and_ev

Instance Attribute Summary

Attributes inherited from EventGenerator

#command, #event_model, #history, #unreachability_reason, #unreachable_handlers

Attributes inherited from PlanObject

#addition_time, #executable, #execution_engine, #finalization_handlers, #finalization_time, #model, #plan, #promise_executor, #removed_at

Attributes included from Transaction::Proxying::Cache

#transaction_forwarder_module, #transaction_proxy_module

Attributes included from Relations::DirectedRelationSupport

#relation_graphs

Attributes inherited from DistributedObject

#local_owner_id, #owners

Instance Method Summary collapse

Methods inherited from EventGenerator

#&, #achieve_asynchronously, #achieve_with, #add_child_object, #call, #call_handlers, #call_unreachable_handlers, #call_without_propagation, #called, #calling, #cancel, #check_call_validity, #check_call_validity_after_calling, #check_emission_validity, #clear_pending, #controlable?, #create_transaction_proxy, #default_command, #delay, #each_precondition, #emit, #emit_failed, #emit_without_propagation, #emitting, #filter, #finalized!, #fire, #fired, #forward, #forward_once, #forward_to, #forward_to_once, #forwarded_to?, #garbage!, #happened?, #if_unreachable, #initialize_copy, #initialize_replacement, #last, #mark_unreachable!, match, #match, #model, #name, #new, #on, #once, #pending, #plan=, #precondition, #pretty_print, #realize_with, #related_events, #related_tasks, #replace_by, #signal, #signals, #signals_once, #to_event, #to_execution_exception, #to_execution_exception_matcher, #unreachable!, #unreachable_without_propagation, #until, #when_unreachable, #|

Methods included from DRoby::Identifiable

#droby_id, #initialize_copy

Methods included from DRoby::V5::DRobyConstant::Dump

#droby_dump, #droby_marshallable?

Methods included from DRoby::V5::EventGeneratorDumper

#droby_dump

Methods included from GUI::RelationsCanvasEventGenerator

#display, #display_create, #display_name, #display_time_end, #display_time_start, priorities, style, styles

Methods included from GUI::RelationsCanvasPlanObject

#display, #display_create, #display_events, #display_name, #display_parent

Methods inherited from PlanObject

#add_child_object, #apply_relation_changes, #as_plan, #can_finalize?, #commit_transaction, #concrete_model, #connection_space, #each_finalization_handler, #each_in_neighbour_merged, #each_out_neighbour_merged, #each_plan_child, #engine, #executable?, #finalized!, #finalized?, #forget_peer, #fullfills?, #garbage!, #garbage?, #initialize_copy, #initialize_replacement, #merged_relations, #promise, #read_write?, #real_object, #remotely_useful?, #replace_by, #replace_subplan_by, #root_object, #root_object?, #subscribed?, #transaction_proxy?, #transaction_stack, #update_on?, #updated_by?, #when_finalized

Methods included from Models::PlanObject

#child_plan_object, #finalization_handler, #match, #when_finalized

Methods included from GUI::GraphvizPlanObject

#apply_layout, #dot_label, #to_dot

Methods included from Relations::DirectedRelationSupport

#[], #[]=, #add_child_object, #add_parent_object, #child_object?, #child_objects, #clear_vertex, #each_child_object, #each_in_neighbour, #each_out_neighbour, #each_parent_object, #each_relation, #each_relation_graph, #each_relation_sorted, #each_root_relation_graph, #enum_child_objects, #enum_parent_objects, #enum_relations, #leaf?, #parent_object?, #parent_objects, #related_object?, #related_objects, #relation_graph_for, #relations, #remove_child_object, #remove_children, #remove_parent_object, #remove_parents, #remove_relations, #root?, #sorted_relations

Methods inherited from DistributedObject

#add_owner, #clear_owners, #initialize_copy, #owned_by?, #remove_owner

Constructor Details

#initializeAndGenerator

Returns a new instance of AndGenerator.



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/roby/and_generator.rb', line 38

def initialize
    super do |context|
        emit_if_achieved(context)
    end

    # This hash is a event_generator => event mapping of the last
    # events of each event generator. We compare the event stored in
    # this hash with the last events of each source to know if the
    # source fired since it has been added to this AndGenerator
    @events = {}

    # This flag is true unless we are not waiting for the emission
    # anymore.
    @active = true
end

Instance Method Details

#<<(generator) ⇒ Object

Add a new source to this generator



129
130
131
132
# File 'lib/roby/and_generator.rb', line 129

def <<(generator)
    generator.add_signal self
    self
end

#added_signal_parent(parent, info) ⇒ Object

Adds a new source to events when a source event is added



97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/roby/and_generator.rb', line 97

def added_signal_parent(parent, info) # :nodoc:
    super
    @events[parent] = parent.last

    # If the parent is unreachable, check that it has neither been
    # removed, nor it has been emitted
    parent.if_unreachable(cancel_at_emission: true) do |reason, event|
        if @events.has_key?(parent) && @events[parent] == parent.last
            @active = false
            unreachable!(reason || parent)
        end
    end
end

#emit_if_achieved(context) ⇒ Object

Helper method that will emit the event if all the sources are emitted.



81
82
83
84
85
86
87
88
89
# File 'lib/roby/and_generator.rb', line 81

def emit_if_achieved(context) # :nodoc:
    return if @events.empty? || !@active

    each_parent_object(EventStructure::Signal) do |source|
        return if @events[source] == source.last
    end
    @active = false
    emit(nil)
end

#empty?Boolean

True if the generator has no sources

Returns:

  • (Boolean)


92
93
94
# File 'lib/roby/and_generator.rb', line 92

def empty?
    relation_graph_for(EventStructure::Signal).root?(self)
end

#eventsObject

The set of source events



119
120
121
# File 'lib/roby/and_generator.rb', line 119

def events
    each_parent_object(EventStructure::Signal).to_set
end

#removed_signal_parent(parent) ⇒ Object

Removes a source from events when the source is removed



112
113
114
115
116
# File 'lib/roby/and_generator.rb', line 112

def removed_signal_parent(parent) # :nodoc:
    super
    @events.delete(parent)
    emit_if_achieved(nil)
end

#resetObject

After this call, the AndGenerator will emit as soon as all its source events have been emitted again.

Example:

a = task1.intermediate_event
b = task2.intermediate_event
and_ev = (a & b)

a.intermediate_event!
b.intermediate_event! # and_ev emits here
a.intermediate_event!
b.intermediate_event! # and_ev does *not* emit

and_ev.reset
a.intermediate_event!
b.intermediate_event! # and_ev emits here


70
71
72
73
74
75
76
77
78
# File 'lib/roby/and_generator.rb', line 70

def reset
    @active = true
    each_parent_object(EventStructure::Signal) do |source|
        @events[source] = source.last
        if source.respond_to?(:reset)
            source.reset
        end
    end
end

#waitingObject

The set of generators that have not been emitted yet.



124
125
126
# File 'lib/roby/and_generator.rb', line 124

def waiting
    each_parent_object(EventStructure::Signal).find_all { |ev| @events[ev] == ev.last }
end