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



286
287
288
289
290
291
292
293
294
295
296
297
298
# File 'lib/roby/coordination/task_state_machine.rb', line 286

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|
        unless 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



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

def namespace
    @namespace ||= nil
end

#namespace=(name) ⇒ Object



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

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


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
284
# File 'lib/roby/coordination/task_state_machine.rb', line 242

def refine_running_state(*args, &block)
    if args.last.kind_of?(Hash)
        options = args.pop
    end
    options = Kernel.validate_options(options || {}, 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



203
204
205
206
207
208
# File 'lib/roby/coordination/task_state_machine.rb', line 203

def state_machine
    if @state_machine then @state_machine
    elsif superclass.respond_to?(:state_machine)
        superclass.state_machine
    end
end