Module: Roby::TaskStateHelper

Included in:
Task
Defined in:
lib/roby/coordination/task_state_machine.rb

Overview

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

Defined Under Namespace

Classes: Proxy

Instance Method Summary collapse

Instance Method Details

#import_events_to_roby(machine) ⇒ Object



285
286
287
288
289
290
291
292
293
294
295
296
297
# 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

#namespaceObject

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



185
186
187
# File 'lib/roby/coordination/task_state_machine.rb', line 185

def namespace
    @namespace ||= nil 
end

#namespace=(name) ⇒ Object



189
190
191
# File 'lib/roby/coordination/task_state_machine.rb', line 189

def namespace=(name)
    @namespace=name
end

#refine_running_state(*args, &block) ⇒ Object

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


241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
# 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_machineObject

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



202
203
204
205
206
207
# 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