module Roby::TaskStateHelper

The TaskStateHelper allows to add a statemachine to a Roby::Task and allows the tracking of events within the 'running' state

Public Instance Methods

import_events_to_roby(machine) click to toggle source
# File lib/roby/coordination/task_state_machine.rb, line 285
def import_events_to_roby(machine)
    # Roby requires the self to be the subclassed Roby::Task
    # Thus embed import into refine_running_state and using eval here
    machine.events.each do |e|
        if !has_event?(e.name)
            event e.name, controlable: true
        end
        # when event is called transition the state_machine
        on(e.name) do |event|
            state_machine.send("#{e.name.to_sym}!")
        end
    end
end
namespace() click to toggle source

The default namespace that is added to statemachine methods, e.g. when action for transitions are defined

# File lib/roby/coordination/task_state_machine.rb, line 185
def namespace
    @namespace ||= nil 
end
namespace=(name) click to toggle source
# File lib/roby/coordination/task_state_machine.rb, line 189
def namespace=(name)
    @namespace=name
end
refine_running_state(*args, &block) click to toggle source

Refine the running state of the Roby::Task using a state machine description. The initial state of the machine is set to 'running' by default.

Example:

refine_running_state do
    on :pause do
        transition [:running] => paused
    end

    on :resume do
        transition [:paused] => :running
    end

    state :paused do
        def poll(task)
            sleep 4
            task.emit :resume
        end
    end
end

Events are translated into roby events and the statemachine in hooked into the on(:yourevent) {|context| … } You can add additional event handlers as ususal using on(:yourevent) .. syntax

The current status (substate of the running state) can be retrieved via

yourtask.state_machine.status
# File lib/roby/coordination/task_state_machine.rb, line 241
def refine_running_state (*args, &block)
    if args.last.kind_of?(Hash) 
        options = args.pop
    end
    options = Kernel.validate_options(options || Hash.new, namespace: nil)

    if options.has_key?(:namespace)
        self.namespace=options[:namespace]
    end

    # Check if a model of a class ancestor already exists
    # If a parent_model exists, prepare the proxy class accordingly
    # The proxy allows us to use the state_machine library even
    # with instances
    if parent_model = self.superclass.state_machine
        proxy_model = Class.new(parent_model.owner_class)
    else
        proxy_model = Class.new(Proxy)
    end

    # Create the state machine instance that will serve as base model
    # for instances of the Roby::Task (or its subclasses) this machine
    # is associated with The namespace allows to pre/postfix
    # automatically generated functions, such as for sending events:
    # <task>.state_machine.pause_<namespace>! or querying the status
    # <task>.state_machine.<namespace>_paused?  Note cannot use :state
    # instead of :status here for yet unknown reason Changing the
    # attribute :status also changes other method definitions, due to
    # meta programming approach of the underlying library, e.g.
    # status_transitions(from: ..., to: ...)

    if self.namespace 
        machine = StateMachine::Machine.find_or_create(proxy_model, :status, initial: :running, namespace: self.namespace)
    else
        machine = StateMachine::Machine.find_or_create(proxy_model, :status, initial: :running)
    end

    machine_loader = StateMachineDefinitionContext.new(self, machine)
    machine_loader.instance_eval(&block)
    @state_machine = machine

    import_events_to_roby(machine)
end
state_machine() click to toggle source

The state machine model that is running on all tasks of this task model

# File lib/roby/coordination/task_state_machine.rb, line 202
def state_machine
    if @state_machine then @state_machine
    elsif superclass.respond_to?(:state_machine)
        superclass.state_machine
    end
end