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, #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

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.



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

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 = Hash.new

    # 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



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

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



92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/roby/and_generator.rb', line 92

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.



79
80
81
82
83
84
85
86
# File 'lib/roby/and_generator.rb', line 79

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)


89
# File 'lib/roby/and_generator.rb', line 89

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

#eventsObject

The set of source events



114
# File 'lib/roby/and_generator.rb', line 114

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



107
108
109
110
111
# File 'lib/roby/and_generator.rb', line 107

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


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

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.



116
# File 'lib/roby/and_generator.rb', line 116

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