Class: Roby::Schedulers::Temporal

Inherits:
Basic show all
Defined in:
lib/roby/schedulers/temporal.rb

Overview

The temporal scheduler adds to the decisions made by the Basic scheduler information given by the temporal constraint network.

See the documentation of Roby::Schedulers for more information

Instance Attribute Summary collapse

Attributes inherited from Basic

#include_children, #plan, #query

Instance Method Summary collapse

Methods inherited from Basic

#basic_scheduling_root_task?, #can_start?, #initial_events

Methods inherited from Reporting

#report_action, #report_holdoff, #report_pending_non_executable_task, #report_trigger

Constructor Details

#initialize(with_basic = true, with_children = true, plan = nil) ⇒ Temporal

Returns a new instance of Temporal.



19
20
21
22
23
24
# File 'lib/roby/schedulers/temporal.rb', line 19

def initialize(with_basic = true, with_children = true, plan = nil)
    super(with_children, plan)
    @basic_constraints = with_basic
    @scheduling_constraints_graph = self.plan
        .event_relation_graph_for(EventStructure::SchedulingConstraints)
end

Instance Attribute Details

#scheduling_constraints_graphObject (readonly)

The proper graph object that contains the scheduling constraints



17
18
19
# File 'lib/roby/schedulers/temporal.rb', line 17

def scheduling_constraints_graph
  @scheduling_constraints_graph
end

Instance Method Details

#can_schedule?(task, time = Time.now, stack = []) ⇒ Boolean

Returns:

  • (Boolean)


26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/roby/schedulers/temporal.rb', line 26

def can_schedule?(task, time = Time.now, stack = [])
    if task.running?
        return true
    elsif !can_start?(task)
        report_holdoff "cannot be started", task
        return false
    end

    return false unless verify_temporal_constraints(task, time, stack)
    return false unless verify_schedule_as_constraints(task, time, stack)
    return true unless basic_constraints?

    root_task = basic_scheduling_root_task?(task)
    if root_task
        true
    elsif include_children && parents_allow_scheduling?(task, time, stack)
        true
    elsif include_children
        report_holdoff "not root, and has no running parent", task
        false
    else
        report_holdoff "not root, and include_children is false", task
        false
    end
end

#parent_waiting_for_self?(task, parent_task) ⇒ Boolean

Returns:

  • (Boolean)


106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/roby/schedulers/temporal.rb', line 106

def parent_waiting_for_self?(task, parent_task)
    # Special case: check in Dependency if there are some
    # parents for which a forward constraint from +self+ to
    # +parent.start_event+ exists. If it is the case, start
    # the task
    parent_task.start_event.each_backward_temporal_constraint do |constraint|
        if constraint.respond_to?(:task) && constraint.task == task
            Schedulers.debug do
                "Temporal: #{task} has no running parent, but " \
                "a constraint from #{constraint} to #{parent_task}.start " \
                "exists. Scheduling."
            end
            return true
        end
    end

    false
end

#parents_allow_scheduling?(task, time, stack) ⇒ Boolean

Returns:

  • (Boolean)


81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/roby/schedulers/temporal.rb', line 81

def parents_allow_scheduling?(task, time, stack)
    task.each_parent_task.any? do |parent_task|
        next(true) if parent_task.running?

        parent_waiting_for_self =
            parent_waiting_for_self?(task, parent_task)

        parent_scheduled_as_self =
            task.start_event.child_object?(
                parent_task.start_event,
                Roby::EventStructure::SchedulingConstraints
            )

        next(false) unless parent_scheduled_as_self || parent_waiting_for_self
        next(true) if stack.include?(parent_task)

        begin
            stack.push task
            can_schedule?(parent_task, time, stack)
        ensure
            stack.pop
        end
    end
end

#verify_schedule_as_constraints(task, time, stack) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/roby/schedulers/temporal.rb', line 52

def verify_schedule_as_constraints(task, time, stack)
    # "backward scheduling constraint" == "schedule_as",
    # that is in this loop, start_event.schedule_as(parent.start_event)
    task.start_event
        .each_backward_scheduling_constraint do |scheduled_as_event|
        scheduled_as_task = scheduled_as_event.task
        next if stack.include?(scheduled_as_task)

        if !scheduled_as_task.executable? &&
           task.depends_on?(scheduled_as_task)
            return false
        end

        begin
            stack.push task
            unless can_schedule?(scheduled_as_task, time, stack)
                report_holdoff(
                    "held by schedule_as(%2)", task, scheduled_as_event
                )
                return false
            end
        ensure
            stack.pop
        end
    end

    true
end

#verify_temporal_constraints(task, time, stack) ⇒ Object



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/roby/schedulers/temporal.rb', line 125

def verify_temporal_constraints(task, time, stack)
    event_filter = lambda do |ev|
        if ev.respond_to?(:task)
            ev.task != task &&
                !stack.include?(ev.task) &&
                !scheduling_constraints_graph.related_tasks?(ev.task, task)
        else
            true
        end
    end

    start_event = task.start_event
    if (failed_temporal = start_event.find_failed_temporal_constraint(time, &event_filter))
        report_holdoff "temporal constraints not met (%2: %3)", task, failed_temporal[0], failed_temporal[1]
        return false
    elsif (failed_occurence = start_event.find_failed_occurence_constraint(true, &event_filter))
        report_holdoff "occurence constraints not met (%2)", task, failed_occurence
        return false
    end

    true
end