class Syskit::TaskContext

In the orocos/rtt, a task context is what is usually called a component.

Subclasses of TaskContext represent these components in Roby plans, an TaskContext instances may be associated with a Deployment task, that represent the underlying deployment process. The link between a task context and its deployment is usually represented by an executed_by relation.

The task configuration step is managed as follows:

Constants

D_DIFFERENT_HOSTS

Value returned by #distance_to when the tasks are in different processes localized on different machines

D_SAME_HOST

Value returned by #distance_to when the tasks are in different processes, but on the same machine

D_SAME_PROCESS

Value returned by #distance_to when the tasks are in the same process

Attributes

last_orogen_state[R]

The last state before we went to #orogen_state

orocos_task[R]
Orocos::TaskContext,Orocos::ROS::Node

the underlying remote task

context object. It is set only when the task context's deployment is running

orogen_model[RW]
Orocos::Generation::TaskDeployment

the model of this deployment

orogen_state[R]

The current state for the orogen task. It is a symbol that represents the state name (i.e. :RUNTIME_ERROR, :RUNNING, …)

properties[R]

Accessor for the task's properties

@example write a property named 'latency'

task.properties.latency = 20

@example read the syskit-side value of the latency property

task.properties.latency # => 20

@example update a complex type

task.properties.position do |p|
   p.x = 10
   p.y = 20
   p.z = 30
   p
end
property_overrides[R]

Accessor for overrides of the configuration values

This is an accessor that works akin to {#properties}. It is used to set values that will override the values in the configuration files at {#configure} time

The expected configuration can later be restored with {#property_overrides}

@see #clear_property_overrides

state_reader[R]

The state reader object used to get state updates from the task

@return [Orocos::TaskContext::StateReader]

Public Class Methods

new(orogen_model: nil, **arguments) click to toggle source
Calls superclass method Syskit::Component.new
# File lib/syskit/task_context.rb, line 95
def initialize(orogen_model: nil, **arguments)
    super(**arguments)

    @orogen_model   = orogen_model ||
        Orocos::Spec::TaskDeployment.new(nil, model.orogen_model)

    properties = Hash.new
    property_overrides = Hash.new
    self.model.orogen_model.each_property do |p|
        type = Roby.app.default_loader.intermediate_type_for(p.type)
        properties[p.name] = LiveProperty.new(self, p.name, type)
        property_overrides[p.name] = Property.new(p.name, type)
    end
    @properties = Properties.new(self, properties)
    @property_overrides = Properties.new(self, property_overrides)

    @current_property_commit = nil

    @setup = false
    @ready_to_start = false
    @required_host = nil
    # This is initalized to one as we known that {#setup} will
    # perform a property update
    @has_pending_property_updates = true
end

Public Instance Methods

added_sink(sink, policy) click to toggle source
Calls superclass method
# File lib/syskit/task_context.rb, line 1173
def added_sink(sink, policy)
    super
    relation_graph_for(Flows::DataFlow).modified_tasks << self
end
apply_configuration(config_type) click to toggle source

Applies the values stored in config_type to the task properties.

It is assumed that config_type responds to each, and that the provided each method yields (name, value) pairs. These pairs are then used to call component.name=value to set the values on the component

# File lib/syskit/task_context.rb, line 1058
def apply_configuration(config_type)
    config_type.each do |name, value|
        if has_property?(name)
            property(name).write(value)
        else
            ::Robot.warn "ignoring field #{name} in configuration of #{orocos_name} (#{model.name})"
        end
    end
end
can_be_deployed_by?(task) click to toggle source

(see Syskit::Component#can_be_deployed_by?)

Calls superclass method Syskit::Component#can_be_deployed_by?
# File lib/syskit/task_context.rb, line 210
def can_be_deployed_by?(task)
    # NOTE: in the two tests below, we use the fact that
    # {#can_merge?} (and therefore {Component#can_be_deployed_by?})
    # already checked that services that have the same name in task
    # and self are actually of identical definition.

    return false if !super

    # First check if there are services that need to be removed.
    # Syskit doesn't support that, so for those we cannot deploy
    # using 'task'
    task.each_required_dynamic_service do |srv|
        if srv.model.remove_when_unused? && !find_data_service(srv.name)
            return false
        end
    end

    # Now check for new services that would require reconfiguration
    # when added. Unlike with remove_when_unused, if 'task' is not
    # setup, we can add the new data services to 'task' and
    # therefore ignore the differences
    return true if !task.setup?

    each_required_dynamic_service do |srv|
        if srv.model.addition_requires_reconfiguration? && !task.find_data_service(srv.name)
            return false
        end
    end

    true
end
can_finalize?() click to toggle source

Whether the task should be kept in plan

Calls superclass method Syskit::Component#can_finalize?
# File lib/syskit/task_context.rb, line 137
def can_finalize?
    super &&
        (!(promise = @current_property_commit) ||
           promise.complete?)
end
clean_dynamic_port_connections(port_names) click to toggle source

Remove connections manually to the dynamic ports

This is called after orocos_task.cleanup, as a task's cleanupHook is supposed to delete all dynamic ports (and therefore disconnect them)

# File lib/syskit/task_context.rb, line 616
def clean_dynamic_port_connections(port_names)
    to_remove = Hash.new
    to_remove.merge!(dynamic_input_port_connections(port_names))
    to_remove.merge!(dynamic_output_port_connections(port_names))
    relation_graph_for(Flows::DataFlow).modified_tasks << self
    to_remove.each do |(source_task, sink_task), connections|
        ActualDataFlow.remove_connections(source_task, sink_task, connections)
    end
end
clear_property_overrides() click to toggle source

Clears the currently defined overrides, and restores the original property values

# File lib/syskit/task_context.rb, line 1043
def clear_property_overrides
    property_overrides.clear_values
    property_overrides.each do |property_override|
        if value = property_override.remote_value
            properties[property_override.name].write(value)
        end
    end
end
commit_properties(promise = self.promise(description: "promise: click to toggle source

Create a promise that will apply the properties stored Syskit-side to the underlying component

This usually does not need to be called, as Syskit queues a property update at the component configuration, and whenever a property gets updated

@return [Roby::Promise]

# File lib/syskit/task_context.rb, line 391
def commit_properties(promise = self.promise(description: "promise:#{self}#commit_properties"))
    promise.on_success(description: "#{self}#commit_properties#init") do
        if finalized? || garbage? || finishing? || finished?
            []
        else
            # NOTE: {#queue_property_update_if_needed}, is a
            # *delayed* property commit. It attempts at doing one
            # batched write for many writes from Property#write.
            #
            # This works because the property-snapshot step (this
            # step) is done within the event loop.

            # Register this as the active property commit
            # for the benefit of {#handle_state_change} and
            # synchronizing with the task stop
            @current_property_commit = promise

            # Reset to false (allowing commit queueing from
            # Property#write) only if the task is starting and/or
            # running. This is because we explicitely commit
            # properties within the setup step, and within the
            # task's start event.
            @has_pending_property_updates = !(starting? || running?)

            each_property.map do |p|
                if p.needs_commit?
                    [p, p.value.dup]
                end
            end.compact
        end
    end
    promise.then(description: "#{self}#commit_properties#write") do |properties|
        properties.map do |p, p_value|
            begin
                p.remote_property.write(p_value)
                [Time.now, p, nil]
            rescue ::Exception => e
                [Time.now, p, e]
            end
        end.compact
    end.on_success(description: "#{self}#commit_properties#update_log") do |result|
        result.map do |timestamp, property, error|
            if error
                execution_engine.add_error(PropertyUpdateError.new(error, property))
            else
                property.update_remote_value(property.value)
                property.update_log(timestamp)
                property
            end
        end.compact
    end

    @has_pending_property_updates = true
    promise
end
commit_properties_if_needed(*args) click to toggle source

Create a promise that will apply the properties stored Syskit-side to the underlying component, but only if the underlying task would have a use for it (e.g. it is running or pending)

It returns a null promise otherwise.

@example apply the next property updates and emit the event once

the properties have been applied, but do not do it if the
underlying task is finished

updated_configuration_event.achieve_asynchronously(
    my_child.commit_properties_if_needed)
# Do the property updates

@return [Roby::Promise,Roby::Promise::Null] @see #commit_properties

# File lib/syskit/task_context.rb, line 375
def commit_properties_if_needed(*args)
    if would_use_property_update?
        commit_properties(*args)
    else
        Roby::Promise.null
    end
end
configure() click to toggle source

Default implementation of the configure method.

This default implementation takes its configuration from State.config.task_name, where task_name is the CORBA task name (i.e. the global name of the task).

It then sets the task properties using the values found there

Calls superclass method Syskit::Component#configure
# File lib/syskit/task_context.rb, line 1004
def configure
    # First, set configuration from the configuration files
    # Note: it can only set properties
    if model.configuration_manager.apply(self, override: true)
        info "applied configuration #{conf} to #{orocos_task.name}"
    end

    # Then set configuration stored in Syskit.conf
    if Syskit.conf.orocos.send("#{orocos_name}?")
        config = Syskit.conf.orocos.send(orocos_name)
        apply_configuration(config)
    end

    # Then set per-device configuration options
    if respond_to?(:each_master_device)
        each_master_device do |device|
            if device.configuration
                apply_configuration(device.configuration)
            elsif device.configuration_block
                device.configuration_block.call(self)
            end
        end
    end

    property_overrides.each do |property_override|
        if property_override.has_value?
            actual_property = properties[property_override.name]
            if actual_property.has_value?
                property_override.update_remote_value(actual_property.read)
            end
            actual_property.write(property_override.read)
        end
    end

    super if defined? super
end
deployment_hints() click to toggle source
Calls superclass method Syskit::Component#deployment_hints
# File lib/syskit/task_context.rb, line 260
def deployment_hints
    hints = requirements.deployment_hints.to_set.dup
    return hints if !hints.empty?

    if respond_to?(:each_master_device)
        each_master_device do |dev|
            hints |= dev.requirements.deployment_hints.to_set
        end
    end
    return hints if !hints.empty?

    super
end
distance_to(other) click to toggle source

Returns a value that represents how the two task contexts are far from each other. The possible return values are:

nil

one or both of the tasks are not deployed

D_SAME_PROCESS

both tasks are in the same process

D_SAME_HOST

both tasks are in different processes, but on the same machine

D_DIFFERENT_HOSTS

both tasks are in different processes localized on different machines

# File lib/syskit/task_context.rb, line 182
def distance_to(other)
    return if !execution_agent || !other.execution_agent
    execution_agent.distance_to(other.execution_agent)
end
distance_to_syskit() click to toggle source

How “far” this process is from the Syskit process

@return one of the {TaskContext}::D_* constants

# File lib/syskit/task_context.rb, line 156
def distance_to_syskit
    execution_agent.distance_to_syskit
end
dynamic_input_port_connections(existing_port_names) click to toggle source

@api private

Helper for {#prepare_for_setup} that enumerates the inbound connections originating from a dynamic output port

# File lib/syskit/task_context.rb, line 630
def dynamic_input_port_connections(existing_port_names)
    to_remove = Hash.new
    real_model = self.model.concrete_model
    dynamic_ports = self.model.each_input_port.find_all do |p|
        !real_model.find_input_port(p.name)
    end
    dynamic_ports = dynamic_ports.map(&:name).to_set

    dynamic_ports.each do |name|
        if existing_port_names.include?(name)
            Syskit.fatal "task #{orocos_task} did not clear #{name}, a dynamic input port, during cleanup, as it should have. Go fix it."
        end
    end

    ActualDataFlow.each_in_neighbour(orocos_task) do |source_task|
        mappings = ActualDataFlow.edge_info(source_task, orocos_task)
        to_remove[[source_task, orocos_task]] = mappings.each_key.find_all do |from_port, to_port|
            dynamic_ports.include?(to_port)
        end
    end
    to_remove
end
dynamic_output_port_connections(existing_port_names) click to toggle source

@api private

Helper for {#prepare_for_setup} that enumerates the outbound connections originating from a dynamic output port

# File lib/syskit/task_context.rb, line 657
def dynamic_output_port_connections(existing_port_names)
    to_remove = Hash.new
    real_model = self.model.concrete_model
    dynamic_ports = self.model.each_output_port.find_all do |p|
        !real_model.find_output_port(p.name)
    end
    dynamic_ports = dynamic_ports.map(&:name).to_set

    dynamic_ports.each do |name|
        if existing_port_names.include?(name)
            Syskit.fatal "task #{orocos_task} did not clear #{name}, a dynamic output port, during cleanup, as it should have. Go fix it."
        end
    end

    ActualDataFlow.each_out_neighbour(orocos_task) do |sink_task|
        mappings = ActualDataFlow.edge_info(orocos_task, sink_task)
        to_remove[[orocos_task, sink_task]] = mappings.each_key.find_all do |from_port, to_port|
            dynamic_ports.include?(from_port)
        end
    end
    to_remove
end
each_property(&block) click to toggle source

Enumerate this task's known properties

# File lib/syskit/task_context.rb, line 306
def each_property(&block)
    properties.each(&block)
end
executable?() click to toggle source

Whether this task context can be started

Under syskit, this can happen only if the task has been setup and all its inputs are connected

Calls superclass method
# File lib/syskit/task_context.rb, line 132
def executable?
    @executable || (@ready_to_start && super)
end
find_property(name) click to toggle source

Resolves a property by name

@param [String] name

# File lib/syskit/task_context.rb, line 331
def find_property(name)
    properties[name.to_str]
end
find_through_method_missing(m, args) click to toggle source
# File lib/syskit/task_context.rb, line 1190
def find_through_method_missing(m, args)
    MetaRuby::DSLs.find_through_method_missing(
        self, m, args, '_property' => :find_property) || super
end
has_property?(name) click to toggle source

Whether this task has a property with the given name

# File lib/syskit/task_context.rb, line 311
def has_property?(name)
    properties.include?(name)
end
has_through_method_missing?(m) click to toggle source
# File lib/syskit/task_context.rb, line 1186
def has_through_method_missing?(m)
    MetaRuby::DSLs.has_through_method_missing?(
        self, m, '_property' => :has_property?) || super
end
in_process?() click to toggle source

Whether this task runs within the Syskit process itself

# File lib/syskit/task_context.rb, line 161
def in_process?
    execution_agent.in_process?
end
initialize_remote_handles(remote_handles) click to toggle source

@api private

Initialize the communication with the remote task

@param [Deployment::RemoteTaskHandles] remote_handles

# File lib/syskit/task_context.rb, line 59
def initialize_remote_handles(remote_handles)
    @orocos_task       = remote_handles.handle
    @orocos_task.model = model.orogen_model
    @state_reader      = remote_handles.state_reader

    remote_handles.default_properties.each do |p, p_value|
        syskit_p = property(p.name)
        syskit_p.remote_property = p
        syskit_p.update_remote_value(p_value)
        syskit_p.update_log_metadata(p.log_metadata)
        if !syskit_p.has_value?
            syskit_p.write(p_value)
        end
    end
end
instanciate_dynamic_input_port(name, type, port) click to toggle source

Adds a new port to this model based on a known dynamic port

@param [String] name the new port's name @param [Orocos::Spec::DynamicInputPort] port the port model, as

returned for instance by Orocos::Spec::TaskContext#find_dynamic_input_ports

@return [Port] the new port

# File lib/syskit/task_context.rb, line 1100
def instanciate_dynamic_input_port(name, type, port)
    specialize
    model.instanciate_dynamic_input_port(name, type, port).bind(self)
end
instanciate_dynamic_output_port(name, type, port) click to toggle source

Adds a new port to this model based on a known dynamic port

@param [String] name the new port's name @param [Orocos::Spec::DynamicOutputPort] port the port model, as

returned for instance by Orocos::Spec::TaskContext#find_dynamic_output_ports

@return [Port] the new port's model

# File lib/syskit/task_context.rb, line 1111
def instanciate_dynamic_output_port(name, type, port)
    specialize
    model.instanciate_dynamic_output_port(name, type, port).bind(self)
end
kill_execution_agent_if_alone() click to toggle source
# File lib/syskit/task_context.rb, line 954
def kill_execution_agent_if_alone
    if execution_agent
        not_loggers = execution_agent.each_executed_task.
            find_all { |t| !Roby.app.syskit_utility_component?(t) }
        if not_loggers.size == 1
            plan.unmark_permanent_task(execution_agent)
            if execution_agent.running?
                execution_agent.stop!
                return true
            end
        end
    end
    false
end
merge(merged_task) click to toggle source

Replaces the given task by this task

@param [TaskContext] merged_task the task that should be replaced @return [void]

Calls superclass method Syskit::Component#merge
# File lib/syskit/task_context.rb, line 246
def merge(merged_task)
    super
    self.required_host ||= merged_task.required_host

    if merged_task.orogen_model && !orogen_model
        self.orogen_model = merged_task.orogen_model
    end

    if merged_task.orocos_task && !orocos_task
        self.orocos_task = merged_task.orocos_task
    end
    nil
end
needs_reconfiguration!() click to toggle source

Make sure that configure will be called on this task before it gets started

See also setup and needs_reconfiguration?

# File lib/syskit/task_context.rb, line 602
def needs_reconfiguration!
    execution_agent.needs_reconfiguration!(orocos_name) if execution_agent
end
needs_reconfiguration?() click to toggle source

If true, configure must be called on this task before it is started. This flag is reset after configure has been called

# File lib/syskit/task_context.rb, line 592
def needs_reconfiguration?
    if execution_agent
        execution_agent.needs_reconfiguration?(orocos_name)
    end
end
on_localhost?() click to toggle source

Whether this task runs on the same host than the Syskit process

# File lib/syskit/task_context.rb, line 166
def on_localhost?
    execution_agent.on_localhost?
end
operation(name) click to toggle source
# File lib/syskit/task_context.rb, line 274
def operation(name)
    orocos_task.operation(name)
end
perform_setup(promise) click to toggle source

(see Syskit::Component#perform_setup)

Calls superclass method Syskit::Component#perform_setup
# File lib/syskit/task_context.rb, line 722
def perform_setup(promise)
    prepare_for_setup(promise)
    # This calls #configure
    super(promise)

    properties_updated_in_configure = false
    promise.on_success(description: "#{self}#perform_setup#log_properties") do
        if self.model.needs_stub?(self)
            self.model.prepare_stub(self)
        end
        if Syskit.conf.logs.conf_logs_enabled?
            each_property do |p|
                p.log_stream = Syskit.conf.logs.log_stream_for(p)
                p.update_log
            end
        end
        properties_updated_in_configure = self.properties.each.any? { |p| p.needs_commit? }
    end
    commit_properties(promise)
    promise.then(description: "#{self}#perform_setup#orocos_task.configure") do
        state = orocos_task.rtt_state
        if properties_updated_in_configure && state != :PRE_OPERATIONAL
            info "properties have been changed within #configure, cleaning up #{self}"
            orocos_task.cleanup(false)
            state = :PRE_OPERATIONAL
        end

        if state == :PRE_OPERATIONAL
            info "setting up #{self}"
            orocos_task.configure(false)
        else
            info "#{self} was already configured"
        end
    end
end
prepare_for_setup(promise) click to toggle source

@api private

Setup operations that must be performed before {Component#perform_setup} is called by {#perform_setup}

# File lib/syskit/task_context.rb, line 684
def prepare_for_setup(promise)
    promise.then(description: "#{self}#prepare_for_setup#read_properties") do
            properties = each_property.map do |syskit_p|
                [syskit_p, syskit_p.remote_property.raw_read]
            end
            [properties, orocos_task.rtt_state]
        end.on_success(description: "#{self}#prepare_for_setup#write properties and needs_reconfiguration") do |properties, state|
            properties.each do |syskit_p, remote_value|
                syskit_p.update_remote_value(remote_value)
            end

            needs_reconfiguration = needs_reconfiguration? ||
                execution_agent.configuration_changed?(
                    orocos_name, self.conf, each_required_dynamic_service.to_set) ||
                self.properties.each.any? { |p| p.needs_commit? }

            if !needs_reconfiguration
                info "not reconfiguring #{self}: the task is already configured as required"
            end
            [needs_reconfiguration, state]
        end.then(description: "#{self}#prepare_for_setup#ensure_pre_operational") do |needs_reconfiguration, state|
            if state == :EXCEPTION
                info "reconfiguring #{self}: the task was in exception state"
                orocos_task.reset_exception(false)
                orocos_task.port_names
            elsif needs_reconfiguration && (state != :PRE_OPERATIONAL)
                info "cleaning up #{self}"
                orocos_task.cleanup(false)
                orocos_task.port_names
            end
        end.on_success(description: "#{self}#prepare_for_setup#clean_dynamic_port_connections") do |port_names|
            if port_names
                clean_dynamic_port_connections(port_names)
            end
        end
end
property(name) click to toggle source

Returns the syskit-side representation of the given property

Properties in Syskit are applied only at configuration time, or when commit_properties is called

# File lib/syskit/task_context.rb, line 319
def property(name)
    name = name.to_s
    if p = find_property(name)
        p
    else
        raise Orocos::InterfaceObjectNotFound.new(self, name), "#{self} has no property called #{name}"
    end
end
queue_property_update_if_needed() click to toggle source

@api private

Queue a remote property update if none are pending

This is used by {Property} on writes. Note that because of the general property update structure, all property updates happening in a single execution cycle will be committed together.

# File lib/syskit/task_context.rb, line 349
def queue_property_update_if_needed
    if !would_use_property_update?
        raise InvalidState, "attempting to queue a property update on a finished or finishing task"
    end

    if !@has_pending_property_updates
        commit_properties.execute
    end
end
read_current_state() click to toggle source

@api private

Pull all state changes that are still queued within the state reader and returns the last one

It is destructive, as it does “forget” any pending state changes currently queued.

# File lib/syskit/task_context.rb, line 513
def read_current_state
    while new_state = state_reader.read_new
        state = new_state
    end
    state || state_reader.read
end
ready_for_setup?(state = nil) click to toggle source

Returns true if this component needs to be setup by calling the setup method, or if it can be used as-is

Calls superclass method
# File lib/syskit/task_context.rb, line 528
def ready_for_setup?(state = nil)
    if execution_agent.configuring?(orocos_name)
        debug { "#{self} not ready for setup: already configuring" }
        return false
    elsif !super()
        return false
    elsif !all_inputs_connected?(only_static: true)
        debug { "#{self} not ready for setup: some static ports are not connected" }
        return false
    elsif !orogen_model || !orocos_task
        debug { "#{self} not ready for setup: no orogen model or no orocos task" }
        return false
    end

    state ||= read_current_state
    configurable_state = [:STOPPED, :PRE_OPERATIONAL].include?(state) ||
        orocos_task.exception_state?(state)
    if configurable_state
        true
    else
        debug { "#{self} not ready for setup: in state #{state}, expected STOPPED, PRE_OPERATIONAL or an exception state" }
        false
    end
end
ready_to_start!() click to toggle source
# File lib/syskit/task_context.rb, line 566
def ready_to_start!
    @ready_to_start = true
end
removed_sink(source) click to toggle source
Calls superclass method
# File lib/syskit/task_context.rb, line 1181
def removed_sink(source)
    super
    relation_graph_for(Flows::DataFlow).modified_tasks << self
end
reusable?() click to toggle source

Tests if this task can be reused in the next deployment run

Calls superclass method
# File lib/syskit/task_context.rb, line 607
def reusable?
    super && (!setup? || !needs_reconfiguration?)
end
self_port_to_orocos_port(port) click to toggle source

Resolves the given Syskit::Port object into the actual Port object on the underlying task.

It should not be used directly. One should usually use Syskit::Port#to_orocos_port instead

@return [Orocos::Port]

# File lib/syskit/task_context.rb, line 1086
def self_port_to_orocos_port(port)
    orocos_port = orocos_task.raw_port(port.name)
    if orocos_port.type != port.type
        raise UnexpectedPortType.new(port, orocos_port.type)
    end
    orocos_port
end
setting_up!(promise) click to toggle source

(see Syskit::Component#setting_up!)_

Calls superclass method Syskit::Component#setting_up!
# File lib/syskit/task_context.rb, line 759
def setting_up!(promise)
    super
    execution_agent.start_configuration(orocos_name)
end
setup?() click to toggle source

Returns true if the underlying Orocos task has been configured and can be started

The general protocol is:

if !setup? && ready_for_setup?
    setup
end
# File lib/syskit/task_context.rb, line 562
def setup?
    @setup
end
setup_failed!(exception) click to toggle source

(see Syskit::Component#setup_failed!)_

Calls superclass method Syskit::Component#setup_failed!
# File lib/syskit/task_context.rb, line 765
def setup_failed!(exception)
    execution_agent.finished_configuration(orocos_name)
    super
end
setup_successful!() click to toggle source

Announces that the task is indeed setup

This is meant for internal use. Don't use it unless you know what you are doing

Calls superclass method Syskit::Component#setup_successful!
# File lib/syskit/task_context.rb, line 574
def setup_successful!
    execution_agent.update_current_configuration(
        orocos_name, model, self.conf.dup, self.each_required_dynamic_service.to_set)
    execution_agent.finished_configuration(orocos_name)

    if all_inputs_connected?
        ready_to_start!
        execution_engine.scheduler.report_action "configured and all inputs connected, marking as executable", self
        Runtime.debug { "#{self} is setup and all its inputs are connected, executable? = #{executable?}" }
    else
        execution_engine.scheduler.report_action "configured, but some connections are pending", self
        Runtime.debug { "#{self} is setup but some of its inputs are not connected, executable = #{executable?}" }
    end
    super
end
state_event(name) click to toggle source

Returns the task's event name that maps to the given component state name

@return [Symbol]

# File lib/syskit/task_context.rb, line 85
def state_event(name)
    model.find_state_event(name)
end
stop_orocos_task() click to toggle source

@api private

Helper method that is called in a separate thread to stop the orocos task, taking into account some corner cases such as a dead task, or a task that raises StateTransitionFailed but stops anyways

# File lib/syskit/task_context.rb, line 876
def stop_orocos_task
    orocos_task.stop(false)
    nil
rescue Orocos::ComError
    # We actually aborted. Notify the callback so that it emits
    # interrupt and stop
    :aborted
rescue Orocos::StateTransitionFailed
    # Use #rtt_state as it has no problem with asynchronous
    # communication, unlike the port-based state updates.
    state = orocos_task.rtt_state
    if state != :RUNNING
        Runtime.debug { "in the interrupt event, StateTransitionFailed: task.state == #{state}" }
        # Nothing to do, the poll block will finalize the task
        nil
    else
        raise
    end
end
stub!(name = nil) click to toggle source

Stub this task context by assigning a {Orocos::RubyTaskContext} to {#orocos_task}

# File lib/syskit/task_context.rb, line 1069
def stub!(name = nil)
    if !name && !orocos_name
        raise ArgumentError, "orocos_task is not set on #{self}, you must provide an explicit name in #stub!"
    end
    if name
        self.orocos_name = name
    end
    self.orocos_task = Orocos::RubyTaskContext.from_orogen_model(orocos_name, model.orogen_model)
end
tid() click to toggle source

@!attribute r tid

@return [Integer] The thread ID of the thread running this task
Beware, the thread might be on a remote machine !
# File lib/syskit/task_context.rb, line 78
def tid
    orocos_task.tid
end
trigger_latency() click to toggle source

Maximum time between the task is sent a trigger signal and the time it is actually triggered

# File lib/syskit/task_context.rb, line 91
def trigger_latency
    orogen_model.worstcase_trigger_latency
end
update_orogen_state() click to toggle source

Called at each cycle to update the #orogen_state attribute for this task using the values read from the state reader

# File lib/syskit/task_context.rb, line 491
def update_orogen_state
    @state_sample ||= state_reader.new_sample
    result, v = state_reader.read_with_result(@state_sample, false)
    if !result
        if !state_reader.connected?
            fatal "terminating #{self}, its state reader #{state_reader} is disconnected"
            aborted!
        end
        return
    elsif v
        @last_orogen_state = @orogen_state
        @orogen_state = v
    end
end
updated_sink(sink, policy) click to toggle source
Calls superclass method
# File lib/syskit/task_context.rb, line 1177
def updated_sink(sink, policy)
    super
    relation_graph_for(Flows::DataFlow).modified_tasks << self
end
validate_orogen_state_from_rtt_state() click to toggle source

Validates that the current value in orogen_state matches the value returned by orocos_task.rtt_state. This is called automatically if validate_orogen_states? is set to true

# File lib/syskit/task_context.rb, line 460
def validate_orogen_state_from_rtt_state
    orogen_state = orogen_state
    rtt_state    = orocos_task.rtt_state
    mismatch =
        case rtt_state
        when :RUNNING
            !orocos_task.runtime_state?(orogen_state)
        when :STOPPED
            orogen_state != :STOPPED
        when :RUNTIME_ERROR
            !orocos_task.error_state?(orogen_state)
        when :FATAL_ERROR
            !orocos_task.fatal_error_state?(orogen_state)
        when :EXCEPTION
            !orocos_task.exception_state?(orogen_state)
        end

    if mismatch
        Runtime.warn "state mismatch on #{self} between state=#{orogen_state} and rtt_state=#{rtt_state}"
        @orogen_state = rtt_state
        handle_state_changes
    end
end
will_never_setup?(state = nil) click to toggle source

Whether this task context will ever be configurable

# File lib/syskit/task_context.rb, line 521
def will_never_setup?(state = nil)
    state ||= read_current_state
    state == :FATAL_ERROR
end
would_use_property_update?() click to toggle source
# File lib/syskit/task_context.rb, line 338
def would_use_property_update?
    pending? || starting? || (running? && !finishing?)
end