Class: Syskit::ConnectionGraph

Inherits:
Roby::Relations::Graph
  • Object
show all
Defined in:
lib/syskit/connection_graph.rb

Overview

Represents the actual connection graph between task context proxies. Its vertices are instances of Orocos::TaskContext, and edges are mappings from [source_port_name, sink_port_name] pairs to the connection policy between these ports.

Syskit::ActualDataFlow is the actual global graph instance in which the overall system connections are maintained in practice. Its vertices are Orocos::TaskContext and the edge information a mapping of the form

(source_port_name, sink_port_name) => policy

Syskit::RequiredDataFlow is the graph instance that manages concrete connections between Syskit::TaskContext (i.e. where all the forwarding through compositions has been removed). It is updated as needed by Runtime::ConnectionManagement#update_required_dataflow_graph. Its vertices are Syskit::TaskContext instances and the edge information a mapping of the form

(source_port_name, sink_port_name) => policy

Syskit::Flows::DataFlow is the flow graph that is generated by the engine. Its vertices are Syskit::Component, it contains “virtual” connections (connections between composition ports and task ports). The edge information is of the form

(source_port_name, sink_port_name) => policy

Since compositions are still in this graph, source_port_name and sink_port_name can be either outputs or inputs. In all the other graphs, they are guaranteed to be output ports resp. input ports.

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#nameObject

Needed for Roby's marshalling (so that we can dump the connection graph as a constant)



36
37
38
# File 'lib/syskit/connection_graph.rb', line 36

def name
  @name
end

Instance Method Details

#add_connections(source_task, sink_task, mappings) ⇒ Object

:nodoc:



67
68
69
# File 'lib/syskit/connection_graph.rb', line 67

def add_connections(source_task, sink_task, mappings) # :nodoc:
    add_edge(source_task, sink_task, mappings)
end

#add_edge(source_task, sink_task, mappings) ⇒ Object



78
79
80
81
82
83
84
# File 'lib/syskit/connection_graph.rb', line 78

def add_edge(source_task, sink_task, mappings)
    if mappings.empty?
        raise ArgumentError, "the connection set is empty"
    end
    freeze_edge_info(mappings)
    super
end

#connected?(source_task, source_port, sink_task, sink_port) ⇒ Boolean

Tests if there is a connection between source_task:source_port and sink_task:sink_port

Returns:

  • (Boolean)


60
61
62
63
64
65
# File 'lib/syskit/connection_graph.rb', line 60

def connected?(source_task, source_port, sink_task, sink_port)
    if !has_edge?(source_task, sink_task)
        return false
    end
    edge_info(source_task, sink_task).has_key?([source_port, sink_port])
end

#each_in_connection(task, port = nil) {|source_task, source_port, sink_port, policy| ... } ⇒ Object

Yield or enumerates incoming connections

Parameters:

  • component (Component)

    the component whose connections we want to enumerate

  • port (#name, String, nil) (defaults to: nil)

    if non-nil, the port for which we want to enumerate the connections (in which case the sink_port yield parameter is guaranteed to be this name). Otherwise, all ports are enumerated.

Yields:

  • each connections

Yield Parameters:

  • source_task (Syskit::TaskContext)

    the source task in the connection

  • source_port (String)

    the source port name on source_task

  • sink_port (String)

    the sink port name on self. If the port argument is non-nil, it is guaranteed to be the same.

  • policy (Hash)

    the connection policy

See Also:

  • each_concrete_output_connection each_output_connection


137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/syskit/connection_graph.rb', line 137

def each_in_connection(task, port = nil)
    return enum_for(__method__, task, port) if !block_given?
    if port.respond_to? :name
        port = port.name
    end

    each_in_neighbour(task) do |source_task|
        edge_info(source_task, task).each do |(source_port, sink_port), policy|
            if !port || (sink_port == port)
                yield(source_task, source_port, sink_port, policy)
            end
        end
    end
end

#each_out_connection(task, port = nil) {|source_port, sink_port, sink_task, policy| ... } ⇒ Object

Yield or enumerates the connections that exist from the output ports of self.

Parameters:

  • source_task (Component)

    the task whose connections are being enumerated

  • port (#name, String, nil) (defaults to: nil)

    if non-nil, the port for which we want to enumerate the connections (in which case the source_port yield parameter is guaranteed to be this name). Otherwise, all ports are enumerated.

Yields:

  • each connections

Yield Parameters:

  • source_port (String)

    the source port name on self. If the port argument is non-nil, it is guaranteed to be the same.

  • sink_port (String)

    the sink port name on sink_task.

  • sink_task (Syskit::Component)

    the sink task in the connection

  • policy (Hash)

    the connection policy



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/syskit/connection_graph.rb', line 171

def each_out_connection(task, port = nil)
    return enum_for(__method__, task, port) if !block_given?
    if port.respond_to? :name
        port = port.name
    end

    each_out_neighbour(task) do |sink_task|
        edge_info(task, sink_task).each do |(source_port, sink_port), policy|
            if !port || (port == source_port)
                yield(source_port, sink_port, sink_task, policy)
            end
        end
    end
    self
end

#freeze_edge_info(mappings) ⇒ Object



71
72
73
74
75
76
# File 'lib/syskit/connection_graph.rb', line 71

def freeze_edge_info(mappings)
    mappings.each do |pair, policy|
        pair.freeze
        policy.freeze
    end.freeze
end

#has_in_connections?(task, port) ⇒ Boolean

Tests if port, which has to be an input port, is connected

Returns:

  • (Boolean)


49
50
51
52
53
54
55
56
# File 'lib/syskit/connection_graph.rb', line 49

def has_in_connections?(task, port)
    each_in_neighbour(task) do |parent_task|
        if edge_info(parent_task, task).each_key.any? { |_, target_port| target_port == port }
            return true
        end
    end
    false
end

#has_out_connections?(task, port) ⇒ Boolean

Tests if port, which has to be an output port, is connected

Returns:

  • (Boolean)


39
40
41
42
43
44
45
46
# File 'lib/syskit/connection_graph.rb', line 39

def has_out_connections?(task, port)
    each_out_neighbour(task) do |child_task|
        if edge_info(task, child_task).each_key.any? { |source_port, _| source_port == port }
            return true
        end
    end
    false
end

#merge_info(source, sink, current_mappings, additional_mappings) ⇒ Object



86
87
88
89
90
91
92
93
94
95
# File 'lib/syskit/connection_graph.rb', line 86

def merge_info(source, sink, current_mappings, additional_mappings)
    merged = current_mappings.merge(additional_mappings) do |k, v1, v2|
        if v1 != v2
            raise ArgumentError, "cannot override policy information by default: trying to override the policy between #{source} and #{sink} from #{k}: #{v1} to #{k}: #{v2}"
        end
        v1
    end
    freeze_edge_info(merged)
    merged
end

#remove_connections(source_task, sink_task, mappings) ⇒ Object

Removes the given set of connections between source_task and sink_task.

mappings is an array of port name pairs [output_port_name, input_port_name]



102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/syskit/connection_graph.rb', line 102

def remove_connections(source_task, sink_task, mappings) # :nodoc:
    current_mappings = edge_info(source_task, sink_task).dup
    mappings.each do |source_port, sink_port|
        current_mappings.delete([source_port, sink_port])
    end
    if current_mappings.empty?
        remove_relation(source_task, sink_task)
        remove_vertex(source_task) if leaf?(source_task) && root?(source_task)
        remove_vertex(sink_task)   if leaf?(sink_task)   && root?(sink_task)
    else
        # To make the relation system call #update_info
        set_edge_info(source_task, sink_task, current_mappings)
    end
end