roby 0.7.3 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +7 -5
- data/Manifest.txt +91 -16
- data/README.txt +24 -24
- data/Rakefile +92 -64
- data/app/config/app.yml +42 -43
- data/app/config/init.rb +26 -0
- data/benchmark/alloc_misc.rb +123 -0
- data/benchmark/discovery_latency.rb +67 -0
- data/benchmark/garbage_collection.rb +48 -0
- data/benchmark/genom.rb +31 -0
- data/benchmark/transactions.rb +62 -0
- data/bin/roby +1 -1
- data/bin/roby-log +16 -6
- data/doc/guide/.gitignore +2 -0
- data/doc/guide/config.yaml +34 -0
- data/doc/guide/ext/init.rb +14 -0
- data/doc/guide/ext/previous_next.rb +40 -0
- data/doc/guide/ext/rdoc_links.rb +33 -0
- data/doc/guide/index.rdoc +16 -0
- data/doc/guide/overview.rdoc +62 -0
- data/doc/guide/plan_modifications.rdoc +67 -0
- data/doc/guide/src/abstraction/achieve_with.page +8 -0
- data/doc/guide/src/abstraction/forwarding.page +8 -0
- data/doc/guide/src/abstraction/hierarchy.page +19 -0
- data/doc/guide/src/abstraction/index.page +28 -0
- data/doc/guide/src/abstraction/task_models.page +13 -0
- data/doc/guide/src/basics.template +6 -0
- data/doc/guide/src/basics/app.page +139 -0
- data/doc/guide/src/basics/code_examples.page +33 -0
- data/doc/guide/src/basics/dry.page +69 -0
- data/doc/guide/src/basics/errors.page +443 -0
- data/doc/guide/src/basics/events.page +179 -0
- data/doc/guide/src/basics/hierarchy.page +275 -0
- data/doc/guide/src/basics/index.page +11 -0
- data/doc/guide/src/basics/log_replay/goForward_1.png +0 -0
- data/doc/guide/src/basics/log_replay/goForward_2.png +0 -0
- data/doc/guide/src/basics/log_replay/goForward_3.png +0 -0
- data/doc/guide/src/basics/log_replay/goForward_4.png +0 -0
- data/doc/guide/src/basics/log_replay/goForward_5.png +0 -0
- data/doc/guide/src/basics/log_replay/hierarchy_error_1.png +0 -0
- data/doc/guide/src/basics/log_replay/hierarchy_error_2.png +0 -0
- data/doc/guide/src/basics/log_replay/hierarchy_error_3.png +0 -0
- data/doc/guide/src/basics/log_replay/plan_repair_1.png +0 -0
- data/doc/guide/src/basics/log_replay/plan_repair_2.png +0 -0
- data/doc/guide/src/basics/log_replay/plan_repair_3.png +0 -0
- data/doc/guide/src/basics/log_replay/plan_repair_4.png +0 -0
- data/doc/guide/src/basics/log_replay/roby_log_main_window.png +0 -0
- data/doc/guide/src/basics/log_replay/roby_log_relation_window.png +0 -0
- data/doc/guide/src/basics/log_replay/roby_replay_event_representation.png +0 -0
- data/doc/guide/src/basics/plan_objects.page +71 -0
- data/doc/guide/src/basics/relations_display.page +203 -0
- data/doc/guide/src/basics/roby_cycle_overview.png +0 -0
- data/doc/guide/src/basics/shell.page +102 -0
- data/doc/guide/src/basics/summary.page +32 -0
- data/doc/guide/src/basics/tasks.page +357 -0
- data/doc/guide/src/basics_shell_header.txt +16 -0
- data/doc/guide/src/cycle/cycle-overview.png +0 -0
- data/doc/guide/src/cycle/cycle-overview.svg +208 -0
- data/doc/guide/src/cycle/error_handling.page +168 -0
- data/doc/guide/src/cycle/error_instantaneous_repair.png +0 -0
- data/doc/guide/src/cycle/error_instantaneous_repair.svg +1224 -0
- data/doc/guide/src/cycle/garbage_collection.page +10 -0
- data/doc/guide/src/cycle/index.page +23 -0
- data/doc/guide/src/cycle/propagation.page +154 -0
- data/doc/guide/src/cycle/propagation_diamond.png +0 -0
- data/doc/guide/src/cycle/propagation_diamond.svg +1279 -0
- data/doc/guide/src/default.css +319 -0
- data/doc/guide/src/default.template +74 -0
- data/doc/guide/src/htmldoc.metainfo +20 -0
- data/doc/guide/src/htmldoc.virtual +18 -0
- data/doc/guide/src/images/bodybg.png +0 -0
- data/doc/guide/src/images/contbg.png +0 -0
- data/doc/guide/src/images/footerbg.png +0 -0
- data/doc/guide/src/images/gradient1.png +0 -0
- data/doc/guide/src/images/gradient2.png +0 -0
- data/doc/guide/src/index.page +7 -0
- data/doc/guide/src/introduction/index.page +29 -0
- data/doc/guide/src/introduction/install.page +133 -0
- data/doc/{papers.rdoc → guide/src/introduction/publications.page} +5 -2
- data/doc/{videos.rdoc → guide/src/introduction/videos.page} +4 -2
- data/doc/guide/src/plugins/fault_tolerance.page +44 -0
- data/doc/guide/src/plugins/index.page +11 -0
- data/doc/guide/src/plugins/subsystems.page +45 -0
- data/doc/guide/src/relations/dependency.page +89 -0
- data/doc/guide/src/relations/index.page +12 -0
- data/doc/misc/update_github +24 -0
- data/doc/tutorials/02-GoForward.rdoc +3 -3
- data/ext/graph/graph.cc +46 -0
- data/lib/roby.rb +57 -22
- data/lib/roby/app.rb +132 -112
- data/lib/roby/app/plugins/rake.rb +21 -0
- data/lib/roby/app/rake.rb +0 -7
- data/lib/roby/app/run.rb +1 -1
- data/lib/roby/app/scripts/distributed.rb +1 -2
- data/lib/roby/app/scripts/generate/bookmarks.rb +1 -1
- data/lib/roby/app/scripts/results.rb +2 -1
- data/lib/roby/app/scripts/run.rb +6 -2
- data/lib/roby/app/scripts/shell.rb +11 -11
- data/lib/roby/config.rb +1 -1
- data/lib/roby/decision_control.rb +62 -3
- data/lib/roby/distributed.rb +4 -0
- data/lib/roby/distributed/base.rb +8 -0
- data/lib/roby/distributed/communication.rb +12 -8
- data/lib/roby/distributed/connection_space.rb +61 -44
- data/lib/roby/distributed/distributed_object.rb +1 -1
- data/lib/roby/distributed/notifications.rb +22 -30
- data/lib/roby/distributed/peer.rb +13 -8
- data/lib/roby/distributed/proxy.rb +5 -5
- data/lib/roby/distributed/subscription.rb +4 -4
- data/lib/roby/distributed/transaction.rb +3 -3
- data/lib/roby/event.rb +176 -110
- data/lib/roby/exceptions.rb +12 -4
- data/lib/roby/execution_engine.rb +1604 -0
- data/lib/roby/external_process_task.rb +225 -0
- data/lib/roby/graph.rb +0 -6
- data/lib/roby/interface.rb +221 -137
- data/lib/roby/log/console.rb +5 -3
- data/lib/roby/log/data_stream.rb +94 -16
- data/lib/roby/log/dot.rb +8 -8
- data/lib/roby/log/event_stream.rb +13 -3
- data/lib/roby/log/file.rb +43 -18
- data/lib/roby/log/gui/basic_display_ui.rb +89 -0
- data/lib/roby/log/gui/chronicle_view_ui.rb +90 -0
- data/lib/roby/log/gui/data_displays.rb +4 -5
- data/lib/roby/log/gui/data_displays_ui.rb +146 -0
- data/lib/roby/log/gui/relations.rb +18 -18
- data/lib/roby/log/gui/relations_ui.rb +120 -0
- data/lib/roby/log/gui/relations_view_ui.rb +144 -0
- data/lib/roby/log/gui/replay.rb +41 -13
- data/lib/roby/log/gui/replay_controls.rb +3 -0
- data/lib/roby/log/gui/replay_controls.ui +133 -110
- data/lib/roby/log/gui/replay_controls_ui.rb +249 -0
- data/lib/roby/log/hooks.rb +19 -18
- data/lib/roby/log/logger.rb +7 -6
- data/lib/roby/log/notifications.rb +4 -4
- data/lib/roby/log/plan_rebuilder.rb +20 -22
- data/lib/roby/log/relations.rb +44 -16
- data/lib/roby/log/server.rb +1 -4
- data/lib/roby/log/timings.rb +88 -19
- data/lib/roby/plan-object.rb +135 -11
- data/lib/roby/plan.rb +408 -224
- data/lib/roby/planning/loops.rb +32 -25
- data/lib/roby/planning/model.rb +157 -51
- data/lib/roby/planning/task.rb +47 -20
- data/lib/roby/query.rb +128 -92
- data/lib/roby/relations.rb +254 -136
- data/lib/roby/relations/conflicts.rb +6 -9
- data/lib/roby/relations/dependency.rb +358 -0
- data/lib/roby/relations/ensured.rb +0 -1
- data/lib/roby/relations/error_handling.rb +0 -1
- data/lib/roby/relations/events.rb +0 -2
- data/lib/roby/relations/executed_by.rb +26 -11
- data/lib/roby/relations/planned_by.rb +14 -14
- data/lib/roby/robot.rb +46 -0
- data/lib/roby/schedulers/basic.rb +34 -0
- data/lib/roby/standalone.rb +4 -0
- data/lib/roby/standard_errors.rb +21 -15
- data/lib/roby/state/events.rb +5 -4
- data/lib/roby/support.rb +107 -6
- data/lib/roby/task-operations.rb +23 -19
- data/lib/roby/task.rb +522 -148
- data/lib/roby/task_index.rb +80 -0
- data/lib/roby/test/common.rb +283 -44
- data/lib/roby/test/distributed.rb +53 -37
- data/lib/roby/test/testcase.rb +9 -204
- data/lib/roby/test/tools.rb +3 -3
- data/lib/roby/transactions.rb +154 -111
- data/lib/roby/transactions/proxy.rb +40 -7
- data/manifest.xml +20 -0
- data/plugins/fault_injection/README.txt +0 -3
- data/plugins/fault_injection/Rakefile +2 -8
- data/plugins/fault_injection/app.rb +1 -1
- data/plugins/fault_injection/fault_injection.rb +3 -3
- data/plugins/fault_injection/test/test_fault_injection.rb +19 -25
- data/plugins/subsystems/README.txt +0 -3
- data/plugins/subsystems/Rakefile +2 -7
- data/plugins/subsystems/app.rb +27 -16
- data/plugins/subsystems/test/app/config/init.rb +3 -0
- data/plugins/subsystems/test/app/planners/main.rb +1 -1
- data/plugins/subsystems/test/app/tasks/services.rb +1 -1
- data/plugins/subsystems/test/test_subsystems.rb +23 -16
- data/test/distributed/test_communication.rb +32 -15
- data/test/distributed/test_connection.rb +28 -26
- data/test/distributed/test_execution.rb +59 -54
- data/test/distributed/test_mixed_plan.rb +34 -34
- data/test/distributed/test_plan_notifications.rb +26 -26
- data/test/distributed/test_protocol.rb +57 -48
- data/test/distributed/test_query.rb +11 -7
- data/test/distributed/test_remote_plan.rb +71 -71
- data/test/distributed/test_transaction.rb +50 -47
- data/test/mockups/external_process +28 -0
- data/test/planning/test_loops.rb +163 -119
- data/test/planning/test_model.rb +3 -3
- data/test/planning/test_task.rb +27 -7
- data/test/relations/test_conflicts.rb +3 -3
- data/test/relations/test_dependency.rb +324 -0
- data/test/relations/test_ensured.rb +2 -2
- data/test/relations/test_executed_by.rb +94 -19
- data/test/relations/test_planned_by.rb +11 -9
- data/test/suite_core.rb +6 -3
- data/test/suite_distributed.rb +1 -0
- data/test/suite_planning.rb +1 -0
- data/test/suite_relations.rb +2 -2
- data/test/tasks/test_external_process.rb +126 -0
- data/test/{test_thread_task.rb → tasks/test_thread_task.rb} +17 -20
- data/test/test_bgl.rb +21 -1
- data/test/test_event.rb +229 -155
- data/test/test_exceptions.rb +79 -80
- data/test/test_execution_engine.rb +987 -0
- data/test/test_gui.rb +1 -1
- data/test/test_interface.rb +11 -5
- data/test/test_log.rb +18 -7
- data/test/test_log_server.rb +1 -0
- data/test/test_plan.rb +229 -395
- data/test/test_query.rb +193 -35
- data/test/test_relations.rb +88 -8
- data/test/test_state.rb +55 -37
- data/test/test_support.rb +1 -1
- data/test/test_task.rb +371 -218
- data/test/test_testcase.rb +32 -16
- data/test/test_transactions.rb +211 -170
- data/test/test_transactions_proxy.rb +37 -19
- metadata +169 -71
- data/.gitignore +0 -29
- data/doc/styles/allison.css +0 -314
- data/doc/styles/allison.js +0 -316
- data/doc/styles/allison.rb +0 -276
- data/doc/styles/jamis.rb +0 -593
- data/lib/roby/control.rb +0 -746
- data/lib/roby/executives/simple.rb +0 -30
- data/lib/roby/propagation.rb +0 -562
- data/lib/roby/relations/hierarchy.rb +0 -239
- data/lib/roby/transactions/updates.rb +0 -139
- data/test/relations/test_hierarchy.rb +0 -158
- data/test/test_control.rb +0 -399
- data/test/test_propagation.rb +0 -210
@@ -64,9 +64,9 @@ module Roby
|
|
64
64
|
# Hook called when a new task is marked as mission. It sends a
|
65
65
|
# PeerServer#plan_set_mission message to the remote host.
|
66
66
|
#
|
67
|
-
# Note that plan will have called the #
|
67
|
+
# Note that plan will have called the #added_tasks hook
|
68
68
|
# beforehand
|
69
|
-
def
|
69
|
+
def added_mission(task)
|
70
70
|
super if defined? super
|
71
71
|
return unless task.distribute? && task.self_owned?
|
72
72
|
|
@@ -80,7 +80,7 @@ module Roby
|
|
80
80
|
|
81
81
|
# Hook called when a new task is not a mission anymore. It sends a
|
82
82
|
# PeerServer#plan_set_mission message to the remote host.
|
83
|
-
def
|
83
|
+
def unmarked_mission(task)
|
84
84
|
super if defined? super
|
85
85
|
return unless task.distribute? && task.self_owned?
|
86
86
|
|
@@ -91,10 +91,10 @@ module Roby
|
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
94
|
-
# Common implementation for the #
|
95
|
-
# #
|
94
|
+
# Common implementation for the #added_events and
|
95
|
+
# #added_tasks hooks. It sends PeerServer#plan_add for
|
96
96
|
# all tasks which can be shared among plan managers
|
97
|
-
def self.
|
97
|
+
def self.added_objects(plan, objects)
|
98
98
|
unless Distributed.updating?(plan)
|
99
99
|
relations = nil
|
100
100
|
Distributed.each_updated_peer(plan) do |peer|
|
@@ -105,24 +105,24 @@ module Roby
|
|
105
105
|
return if objects.empty?
|
106
106
|
relations = Distributed.subgraph_of(objects)
|
107
107
|
end
|
108
|
-
peer.transmit(:
|
108
|
+
peer.transmit(:plan_add, plan, objects, relations)
|
109
109
|
end
|
110
110
|
Distributed.trigger(*objects)
|
111
111
|
end
|
112
112
|
end
|
113
|
-
# New tasks have been
|
113
|
+
# New tasks have been added in the plan.
|
114
114
|
#
|
115
|
-
# See PlanModificationHooks.
|
116
|
-
def
|
115
|
+
# See PlanModificationHooks.added_objects
|
116
|
+
def added_tasks(tasks)
|
117
117
|
super if defined? super
|
118
|
-
PlanModificationHooks.
|
118
|
+
PlanModificationHooks.added_objects(self, tasks)
|
119
119
|
end
|
120
|
-
# New free events have been
|
120
|
+
# New free events have been added in the plan.
|
121
121
|
#
|
122
|
-
# See PlanModificationHooks.
|
123
|
-
def
|
122
|
+
# See PlanModificationHooks.added_objects
|
123
|
+
def added_events(events)
|
124
124
|
super if defined? super
|
125
|
-
PlanModificationHooks.
|
125
|
+
PlanModificationHooks.added_objects(self, events)
|
126
126
|
end
|
127
127
|
|
128
128
|
# Hook called when +from+ has been replaced by +to+ in the plan.
|
@@ -190,9 +190,9 @@ module Roby
|
|
190
190
|
task = peer.local_object(task)
|
191
191
|
if plan.owns?(task)
|
192
192
|
if flag
|
193
|
-
plan.
|
193
|
+
plan.add_mission(task)
|
194
194
|
else
|
195
|
-
plan.
|
195
|
+
plan.remove_mission(task)
|
196
196
|
end
|
197
197
|
else
|
198
198
|
task.mission = flag
|
@@ -201,14 +201,14 @@ module Roby
|
|
201
201
|
end
|
202
202
|
|
203
203
|
# Message received when the set of tasks +m_tasks+ has been
|
204
|
-
#
|
204
|
+
# added by the remote plan. +m_relations+ describes the
|
205
205
|
# internal relations between elements of +m_tasks+. It is in a
|
206
206
|
# format suitable for PeerServer#set_relations.
|
207
|
-
def
|
207
|
+
def plan_add(plan, m_tasks, m_relations)
|
208
208
|
Distributed.update(plan = peer.local_object(plan)) do
|
209
209
|
tasks = peer.local_object(m_tasks).to_value_set
|
210
210
|
Distributed.update_all(tasks) do
|
211
|
-
plan.
|
211
|
+
plan.add(tasks)
|
212
212
|
m_relations.each_slice(2) do |obj, rel|
|
213
213
|
set_relations(obj, rel)
|
214
214
|
end
|
@@ -429,7 +429,7 @@ module Roby
|
|
429
429
|
|
430
430
|
event = event_for(from_generator, event_id, time, context)
|
431
431
|
|
432
|
-
event.send(:propagation_id=,
|
432
|
+
event.send(:propagation_id=, from_generator.plan.engine.propagation_id)
|
433
433
|
from_generator.instance_variable_set("@happened", true)
|
434
434
|
from_generator.fired(event)
|
435
435
|
from_generator.call_handlers(event)
|
@@ -450,7 +450,7 @@ module Roby
|
|
450
450
|
|
451
451
|
# Only add the signalling if we own +to+
|
452
452
|
if to_generator.self_owned?
|
453
|
-
|
453
|
+
to_generator.plan.engine.add_event_propagation(only_forward, [event], to_generator, event.context, nil)
|
454
454
|
else
|
455
455
|
# Call #signalling or #forwarding to make
|
456
456
|
# +from_generator+ look like as if the event was really
|
@@ -527,13 +527,5 @@ module Roby
|
|
527
527
|
nil
|
528
528
|
end
|
529
529
|
end
|
530
|
-
|
531
|
-
Roby::Control.at_cycle_end do
|
532
|
-
peers.each_value do |peer|
|
533
|
-
if peer.connected?
|
534
|
-
peer.transmit(:state_update, Roby::State)
|
535
|
-
end
|
536
|
-
end
|
537
|
-
end
|
538
530
|
end
|
539
531
|
end
|
@@ -10,7 +10,7 @@ require 'roby/distributed/proxy'
|
|
10
10
|
require 'roby/distributed/communication'
|
11
11
|
|
12
12
|
module Roby
|
13
|
-
class
|
13
|
+
class ExecutionEngine; include DRbUndumped end
|
14
14
|
end
|
15
15
|
|
16
16
|
module Roby::Distributed
|
@@ -149,7 +149,7 @@ module Roby::Distributed
|
|
149
149
|
# +matcher+ changes
|
150
150
|
def add_trigger(id, matcher)
|
151
151
|
triggers[id] = [matcher, (triggered = ValueSet.new)]
|
152
|
-
Roby.info "#{remote_name} wants notification on #{matcher} (#{id})"
|
152
|
+
Roby::Distributed.info "#{remote_name} wants notification on #{matcher} (#{id})"
|
153
153
|
|
154
154
|
peer.queueing do
|
155
155
|
matcher.each(plan) do |task|
|
@@ -164,7 +164,7 @@ module Roby::Distributed
|
|
164
164
|
|
165
165
|
# Remove the trigger +id+ defined by this peer
|
166
166
|
def remove_trigger(id)
|
167
|
-
Roby.info "#{remote_name} removed #{id} notification"
|
167
|
+
Roby::Distributed.info "#{remote_name} removed #{id} notification"
|
168
168
|
triggers.delete(id)
|
169
169
|
nil
|
170
170
|
end
|
@@ -276,6 +276,11 @@ module Roby::Distributed
|
|
276
276
|
# The remote state
|
277
277
|
attr_accessor :state
|
278
278
|
|
279
|
+
# The plan associated to our connection space
|
280
|
+
def plan; connection_space.plan end
|
281
|
+
# The execution engine associated to #plan
|
282
|
+
def engine; connection_space.plan.engine end
|
283
|
+
|
279
284
|
# Creates a Peer object for the peer connected at +socket+. This peer
|
280
285
|
# is to be managed by +connection_space+ If a block is given, it is
|
281
286
|
# called in the control thread when the connection is finalized
|
@@ -310,8 +315,8 @@ module Roby::Distributed
|
|
310
315
|
local_server.state_update remote_state
|
311
316
|
|
312
317
|
@task = ConnectionTask.new :peer => self
|
313
|
-
|
314
|
-
connection_space.plan.
|
318
|
+
connection_space.plan.engine.once do
|
319
|
+
connection_space.plan.add_permanent(task)
|
315
320
|
task.start!
|
316
321
|
task.emit(:ready)
|
317
322
|
end
|
@@ -362,7 +367,7 @@ module Roby::Distributed
|
|
362
367
|
end
|
363
368
|
|
364
369
|
ensure
|
365
|
-
Roby
|
370
|
+
Roby.synchronize do
|
366
371
|
if result_set
|
367
372
|
result_set.each do |task|
|
368
373
|
Roby::Distributed.keep.deref(task)
|
@@ -407,7 +412,7 @@ module Roby::Distributed
|
|
407
412
|
trigger.last.call(task)
|
408
413
|
end
|
409
414
|
rescue Exception
|
410
|
-
Roby.warn "trigger handler #{trigger.last} failed with #{$!.full_message}"
|
415
|
+
Roby::Distributed.warn "trigger handler #{trigger.last} failed with #{$!.full_message}"
|
411
416
|
ensure
|
412
417
|
Roby::Distributed.keep.deref(task)
|
413
418
|
end
|
@@ -539,7 +544,7 @@ module Roby::Distributed
|
|
539
544
|
|
540
545
|
yield(local_object(remote_object(object)))
|
541
546
|
|
542
|
-
Roby
|
547
|
+
Roby.synchronize do
|
543
548
|
objects.each { |obj| Roby::Distributed.keep.deref(obj) }
|
544
549
|
end
|
545
550
|
end
|
@@ -83,7 +83,7 @@ module Roby
|
|
83
83
|
plan = peer.local_object(self.plan)
|
84
84
|
return if proxy.plan == plan
|
85
85
|
Distributed.update_all([plan, proxy]) do
|
86
|
-
plan.
|
86
|
+
plan.add(proxy)
|
87
87
|
end
|
88
88
|
end
|
89
89
|
end
|
@@ -218,7 +218,7 @@ module Roby
|
|
218
218
|
def droby_dump(dest)
|
219
219
|
DRoby.new(remote_siblings.droby_dump(dest), owners.droby_dump(dest),
|
220
220
|
model.droby_dump(dest), plan.droby_dump(dest),
|
221
|
-
Distributed.format(
|
221
|
+
Distributed.format(meaningful_arguments, dest), Distributed.format(data, dest),
|
222
222
|
:mission => mission?, :started => started?,
|
223
223
|
:finished => finished?, :success => success?)
|
224
224
|
end
|
@@ -271,12 +271,12 @@ module Roby
|
|
271
271
|
task.success = flags[:success]
|
272
272
|
|
273
273
|
if task.mission? != flags[:mission]
|
274
|
-
plan = peer.local_object(self.plan) ||
|
274
|
+
plan = peer.local_object(self.plan) || peer.connection_space.plan
|
275
275
|
if plan.owns?(task)
|
276
276
|
if flags[:mission]
|
277
|
-
plan.
|
277
|
+
plan.add_mission(task)
|
278
278
|
else
|
279
|
-
plan.
|
279
|
+
plan.remove_mission(task)
|
280
280
|
end
|
281
281
|
else
|
282
282
|
task.mission = flags[:mission]
|
@@ -39,14 +39,14 @@ module Roby
|
|
39
39
|
|
40
40
|
# The peer wants to subscribe to our main plan
|
41
41
|
def subscribe_plan(sibling)
|
42
|
-
added_sibling(
|
43
|
-
peer.transmit(:subscribed_plan,
|
44
|
-
subscribe(
|
42
|
+
added_sibling(peer.connection_space.plan.remote_id, sibling)
|
43
|
+
peer.transmit(:subscribed_plan, peer.connection_space.plan.remote_id)
|
44
|
+
subscribe(peer.connection_space.plan)
|
45
45
|
end
|
46
46
|
|
47
47
|
# Called by our peer because it has subscribed us to its main plan
|
48
48
|
def subscribed_plan(remote_plan_id)
|
49
|
-
peer.proxies[remote_plan_id] =
|
49
|
+
peer.proxies[remote_plan_id] = peer.connection_space.plan
|
50
50
|
peer.remote_plan = remote_plan_id
|
51
51
|
end
|
52
52
|
|
@@ -133,7 +133,7 @@ module Roby
|
|
133
133
|
end
|
134
134
|
end
|
135
135
|
|
136
|
-
def
|
136
|
+
def add(objects) # :nodoc:
|
137
137
|
if objects
|
138
138
|
events, tasks = partition_event_task(objects)
|
139
139
|
for object in (events || []) + (tasks || [])
|
@@ -360,8 +360,8 @@ module Roby
|
|
360
360
|
begin
|
361
361
|
Distributed.transaction_handler[trsc] if Distributed.transaction_handler
|
362
362
|
rescue
|
363
|
-
Roby.warn "transaction handler for #{trsc} failed"
|
364
|
-
Roby.warn $!.full_message
|
363
|
+
Roby::Distributed.warn "transaction handler for #{trsc} failed"
|
364
|
+
Roby::Distributed.warn $!.full_message
|
365
365
|
trsc.invalidate("failed transaction handler")
|
366
366
|
end
|
367
367
|
end
|
data/lib/roby/event.rb
CHANGED
@@ -1,8 +1,3 @@
|
|
1
|
-
require 'utilrb/weakref'
|
2
|
-
require 'roby/plan-object'
|
3
|
-
require 'roby/exceptions'
|
4
|
-
require 'set'
|
5
|
-
|
6
1
|
module Roby
|
7
2
|
# Event objects are the objects representing a particular emission in the
|
8
3
|
# event propagation process. They represent the common propagation
|
@@ -22,7 +17,7 @@ module Roby
|
|
22
17
|
attr_accessor :propagation_id, :context, :time
|
23
18
|
protected :propagation_id=, :context=, :time=
|
24
19
|
|
25
|
-
# The events whose emission triggered this event during the
|
20
|
+
# The events whose emission directly triggered this event during the
|
26
21
|
# propagation. The events in this set are subject to Ruby's own
|
27
22
|
# garbage collection, which means that if a source event is garbage
|
28
23
|
# collected (i.e. if all references to the associated task/event
|
@@ -108,12 +103,6 @@ module Roby
|
|
108
103
|
# * #forwarding
|
109
104
|
#
|
110
105
|
class EventGenerator < PlanObject
|
111
|
-
attr_writer :executable
|
112
|
-
|
113
|
-
# True if this event is executable. A non-executable event cannot be
|
114
|
-
# called even if it is controlable
|
115
|
-
def executable?; @executable end
|
116
|
-
|
117
106
|
# Creates a new Event generator which is emitted as soon as one of this
|
118
107
|
# object and +generator+ is emitted
|
119
108
|
def |(generator)
|
@@ -127,6 +116,7 @@ module Roby
|
|
127
116
|
end
|
128
117
|
|
129
118
|
attr_enumerable(:handler, :handlers) { Array.new }
|
119
|
+
attr_enumerable(:once_handler, :once_handlers) { Array.new }
|
130
120
|
|
131
121
|
def initialize_copy(old) # :nodoc:
|
132
122
|
super
|
@@ -170,7 +160,6 @@ module Roby
|
|
170
160
|
end
|
171
161
|
end
|
172
162
|
super() if defined? super
|
173
|
-
@executable = true
|
174
163
|
|
175
164
|
end
|
176
165
|
|
@@ -187,13 +176,15 @@ module Roby
|
|
187
176
|
# Checks that the event can be called. Raises various exception
|
188
177
|
# when it is not the case.
|
189
178
|
def check_call_validity
|
190
|
-
|
191
|
-
raise
|
179
|
+
if !plan
|
180
|
+
raise EventNotExecutable.new(self), "#emit called on #{self} which is in no plan"
|
181
|
+
elsif !engine
|
182
|
+
raise EventNotExecutable.new(self), "#emit called on #{self} which is has no associated execution engine"
|
183
|
+
elsif !engine.allow_propagation?
|
184
|
+
raise PhaseMismatch, "call to #emit is not allowed in this context"
|
192
185
|
elsif !controlable?
|
193
186
|
raise EventNotControlable.new(self), "#call called on a non-controlable event"
|
194
|
-
elsif !
|
195
|
-
raise EventNotExecutable.new(self), "#call called on #{self} which is non-executable event"
|
196
|
-
elsif !Roby.inside_control?
|
187
|
+
elsif !engine.inside_control?
|
197
188
|
raise ThreadMismatch, "#call called while not in control thread"
|
198
189
|
end
|
199
190
|
end
|
@@ -202,21 +193,22 @@ module Roby
|
|
202
193
|
# when it is not the case.
|
203
194
|
def check_emission_validity
|
204
195
|
if !executable?
|
205
|
-
raise EventNotExecutable.new(self), "#emit called on #{self} which is
|
206
|
-
|
207
|
-
|
208
|
-
elsif !
|
196
|
+
raise EventNotExecutable.new(self), "#emit called on #{self} which is a non-executable event"
|
197
|
+
elsif !engine.allow_propagation?
|
198
|
+
raise PhaseMismatch, "call to #emit is not allowed in this context"
|
199
|
+
elsif !engine.inside_control?
|
209
200
|
raise ThreadMismatch, "#emit called while not in control thread"
|
210
201
|
end
|
211
202
|
end
|
212
203
|
|
213
204
|
# Returns true if the command has been called and false otherwise
|
214
205
|
# The command won't be called if #postpone() is called within the
|
215
|
-
# #calling hook
|
206
|
+
# #calling hook, in which case the method returns false.
|
216
207
|
#
|
217
208
|
# This is used by propagation code, and should never be called directly
|
218
|
-
def call_without_propagation(context)
|
209
|
+
def call_without_propagation(context)
|
219
210
|
check_call_validity
|
211
|
+
|
220
212
|
if !controlable?
|
221
213
|
raise EventNotControlable.new(self), "#call called on a non-controlable event"
|
222
214
|
end
|
@@ -225,7 +217,11 @@ module Roby
|
|
225
217
|
calling(context)
|
226
218
|
@pending = true
|
227
219
|
|
228
|
-
|
220
|
+
if !executable?
|
221
|
+
raise EventNotExecutable.new(self), "#call called on #{self} which is a non-executable event"
|
222
|
+
end
|
223
|
+
|
224
|
+
plan.engine.propagation_context([self]) do
|
229
225
|
command[context]
|
230
226
|
end
|
231
227
|
|
@@ -252,36 +248,46 @@ module Roby
|
|
252
248
|
def call(*context)
|
253
249
|
check_call_validity
|
254
250
|
|
251
|
+
# This test must not be done in #emit_without_propagation as the
|
252
|
+
# other ones: it is possible, using Distributed.update, to disable
|
253
|
+
# ownership tests, but that does not work if the test is in
|
254
|
+
# #emit_without_propagation
|
255
|
+
if !self_owned?
|
256
|
+
raise OwnershipError, "not owner"
|
257
|
+
end
|
258
|
+
|
255
259
|
context.compact!
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
260
|
+
engine = plan.engine
|
261
|
+
if engine.gathering?
|
262
|
+
engine.add_event_propagation(false, engine.propagation_sources, self, (context unless context.empty?), nil)
|
263
|
+
else
|
264
|
+
Roby.synchronize do
|
265
|
+
errors = engine.propagate_events do |initial_set|
|
266
|
+
engine.add_event_propagation(false, nil, self, (context unless context.empty?), nil)
|
262
267
|
end
|
263
268
|
if errors.size == 1
|
264
269
|
e = errors.first.exception
|
265
|
-
raise e, e.message, e.backtrace
|
270
|
+
raise e.dup, e.message, Roby.filter_backtrace(e.backtrace)
|
266
271
|
elsif !errors.empty?
|
267
272
|
for e in errors
|
268
|
-
|
273
|
+
pp e.exception
|
269
274
|
end
|
275
|
+
raise "multiple exceptions"
|
270
276
|
end
|
271
277
|
end
|
272
278
|
end
|
273
279
|
end
|
274
280
|
|
275
|
-
#
|
276
|
-
|
281
|
+
# call-seq:
|
282
|
+
# on { |event| ... }
|
277
283
|
#
|
278
|
-
#
|
279
|
-
#
|
280
|
-
#
|
281
|
-
# the absolute point in time at which this propagation must happen.
|
284
|
+
# Adds an event handler on this generator. The block gets an Event
|
285
|
+
# object which describes the parameters of the emission (context value,
|
286
|
+
# time, ...). See Event for details.
|
282
287
|
def on(signal = nil, time = nil, &handler)
|
283
288
|
if signal
|
284
|
-
|
289
|
+
Roby.warn_deprecated "EventGenerator#on only accepts event handlers now. Use #signals to establish signalling"
|
290
|
+
self.signals(signal, time)
|
285
291
|
end
|
286
292
|
|
287
293
|
if handler
|
@@ -299,14 +305,19 @@ module Roby
|
|
299
305
|
# :at => time association. In the first case, +time+ is a floating-point
|
300
306
|
# delay in seconds and in the second case it is a Time object which is
|
301
307
|
# the absolute point in time at which this propagation must happen.
|
302
|
-
|
308
|
+
def signals(generator, timespec = nil)
|
303
309
|
if !generator.controlable?
|
304
|
-
raise EventNotControlable.new(self), "trying to establish a signal
|
310
|
+
raise EventNotControlable.new(self), "trying to establish a signal from #{self} to #{generator} which is not controllable"
|
305
311
|
end
|
306
|
-
timespec =
|
312
|
+
timespec = ExecutionEngine.validate_timespec(timespec)
|
307
313
|
|
308
314
|
add_signal generator, timespec
|
309
315
|
self
|
316
|
+
end
|
317
|
+
|
318
|
+
def signal(generator, timespec = nil)
|
319
|
+
Roby.warn_deprecated "EventGenerator#signal has been renamed into EventGenerator#signals"
|
320
|
+
signals(generator, timespec)
|
310
321
|
end
|
311
322
|
|
312
323
|
# A set of blocks called when this event cannot be emitted again
|
@@ -338,6 +349,11 @@ module Roby
|
|
338
349
|
@unreachable_event
|
339
350
|
end
|
340
351
|
|
352
|
+
def forward(generator, timespec = nil)
|
353
|
+
Roby.warn_deprecated "EventGenerator#forward has been renamed into EventGenerator#forward_to"
|
354
|
+
forward_to(generator, timespec)
|
355
|
+
end
|
356
|
+
|
341
357
|
# Emit +generator+ when +self+ is fired, without calling the command of
|
342
358
|
# +generator+, if any.
|
343
359
|
#
|
@@ -345,44 +361,57 @@ module Roby
|
|
345
361
|
# :at => time association. In the first case, +time+ is a floating-point
|
346
362
|
# delay in seconds and in the second case it is a Time object which is
|
347
363
|
# the absolute point in time at which this propagation must happen.
|
348
|
-
|
349
|
-
timespec =
|
364
|
+
def forward_to(generator, timespec = nil)
|
365
|
+
timespec = ExecutionEngine.validate_timespec(timespec)
|
350
366
|
add_forwarding generator, timespec
|
351
367
|
self
|
352
|
-
|
368
|
+
end
|
353
369
|
|
354
370
|
# Returns an event which is emitted +seconds+ seconds after this one
|
355
371
|
def delay(seconds)
|
356
372
|
if seconds == 0 then self
|
357
373
|
else
|
358
374
|
ev = EventGenerator.new
|
359
|
-
|
375
|
+
forward_to(ev, :delay => seconds)
|
360
376
|
ev
|
361
377
|
end
|
362
378
|
end
|
363
379
|
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
# event only once.
|
370
|
-
def once(signal = nil, time = nil)
|
371
|
-
handler = nil
|
372
|
-
on(signal, time) do |context|
|
373
|
-
yield(context) if block_given?
|
374
|
-
self.handlers.delete(handler)
|
375
|
-
remove_signal(signal) if signal
|
380
|
+
# Signals the given target event only once
|
381
|
+
def signals_once(signal, delay = nil)
|
382
|
+
signals(signal, delay)
|
383
|
+
once do |context|
|
384
|
+
remove_signal signal
|
376
385
|
end
|
377
|
-
|
386
|
+
self
|
387
|
+
end
|
388
|
+
|
389
|
+
# call-seq:
|
390
|
+
# once { |context| ... }
|
391
|
+
#
|
392
|
+
# Calls the provided event handler only once
|
393
|
+
def once(signal = nil, time = nil, &block)
|
394
|
+
if signal
|
395
|
+
Roby.warn_deprecated "the once(event_name) form has been replaced by #signal_once"
|
396
|
+
signal_once(signal, time)
|
397
|
+
end
|
398
|
+
|
399
|
+
once_handlers << block
|
400
|
+
self
|
378
401
|
end
|
379
402
|
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
403
|
+
def forward_once(ev, delay = nil)
|
404
|
+
Roby.warn_deprecated "#forward_once has been renamed into #forward_to_once"
|
405
|
+
forward_to_once(ev)
|
406
|
+
end
|
407
|
+
|
408
|
+
# Forwards to the given target event only once
|
409
|
+
def forward_to_once(ev, delay = nil)
|
410
|
+
forward_to(ev, delay)
|
411
|
+
once do |context|
|
384
412
|
remove_forwarding ev
|
385
413
|
end
|
414
|
+
self
|
386
415
|
end
|
387
416
|
|
388
417
|
def to_event; self end
|
@@ -401,7 +430,7 @@ module Roby
|
|
401
430
|
end
|
402
431
|
|
403
432
|
# Create a new event object for +context+
|
404
|
-
def new(context); Event.new(self,
|
433
|
+
def new(context); Event.new(self, plan.engine.propagation_id, context, Time.now) end
|
405
434
|
|
406
435
|
# Adds a propagation originating from this event to event propagation
|
407
436
|
def add_propagation(only_forward, event, signalled, context, timespec) # :nodoc:
|
@@ -411,7 +440,7 @@ module Roby
|
|
411
440
|
raise PropagationError, "trying to signal #{signalled} from #{self}"
|
412
441
|
end
|
413
442
|
|
414
|
-
|
443
|
+
plan.engine.add_event_propagation(only_forward, [event], signalled, context, timespec)
|
415
444
|
end
|
416
445
|
private :add_propagation
|
417
446
|
|
@@ -420,7 +449,7 @@ module Roby
|
|
420
449
|
#
|
421
450
|
# This method is always called in a propagation context
|
422
451
|
def fire(event)
|
423
|
-
|
452
|
+
plan.engine.propagation_context([event]) do |result|
|
424
453
|
each_signal do |signalled|
|
425
454
|
add_propagation(false, event, signalled, event.context, self[signalled, EventStructure::Signal])
|
426
455
|
end
|
@@ -446,9 +475,17 @@ module Roby
|
|
446
475
|
begin
|
447
476
|
h.call(event)
|
448
477
|
rescue Exception => e
|
449
|
-
|
478
|
+
plan.engine.add_error( EventHandlerError.new(e, event) )
|
450
479
|
end
|
451
480
|
end
|
481
|
+
each_once_handler do |h|
|
482
|
+
begin
|
483
|
+
h.call(event)
|
484
|
+
rescue Exception => e
|
485
|
+
plan.engine_add_error( EventHandlerError.new(e, event) )
|
486
|
+
end
|
487
|
+
end
|
488
|
+
once_handlers.clear
|
452
489
|
end
|
453
490
|
|
454
491
|
# Raises an exception object when an event whose command has been
|
@@ -457,30 +494,41 @@ module Roby
|
|
457
494
|
what, message = *what
|
458
495
|
what ||= EmissionFailed
|
459
496
|
|
460
|
-
if !message && what.
|
497
|
+
if !message && !(what.kind_of?(Class) || what.kind_of?(Exception))
|
461
498
|
message = what.to_str
|
462
499
|
what = EmissionFailed
|
463
500
|
end
|
464
501
|
|
465
|
-
failure_message =
|
502
|
+
failure_message =
|
503
|
+
if message then "failed to emit #{self}: #{message}"
|
504
|
+
elsif what.respond_to?(:message) then "failed to emit #{self}: #{what.message}"
|
505
|
+
else "failed to emit #{self}: #{message}"
|
506
|
+
end
|
507
|
+
|
466
508
|
error = if Class === what then what.new(nil, self)
|
467
509
|
else what
|
468
510
|
end
|
469
|
-
error = error.exception failure_message
|
470
511
|
|
471
|
-
|
512
|
+
new_error = error.exception failure_message
|
513
|
+
new_error.set_backtrace error.backtrace
|
514
|
+
error = new_error
|
472
515
|
|
516
|
+
if !error.kind_of?(LocalizedError)
|
517
|
+
error = EmissionFailed.new(error, self)
|
518
|
+
end
|
519
|
+
|
520
|
+
plan.engine.add_error(error)
|
473
521
|
ensure
|
474
522
|
@pending = false
|
475
523
|
end
|
476
524
|
|
477
525
|
# Emits the event regardless of wether we are in a propagation context
|
478
|
-
# or not Returns true to match the behavior of
|
479
|
-
# #call_without_propagation
|
526
|
+
# or not. Returns true to match the behavior of #call_without_propagation
|
480
527
|
#
|
481
528
|
# This is used by event propagation. Do not call directly: use #call instead
|
482
|
-
def emit_without_propagation(context)
|
529
|
+
def emit_without_propagation(context)
|
483
530
|
check_emission_validity
|
531
|
+
|
484
532
|
if !executable?
|
485
533
|
raise EventNotExecutable.new(self), "#emit called on #{self} which is not executable"
|
486
534
|
end
|
@@ -492,7 +540,7 @@ module Roby
|
|
492
540
|
unless event.respond_to?(:context)
|
493
541
|
raise TypeError, "#{event} is not a valid event object in #{self}"
|
494
542
|
end
|
495
|
-
event.sources =
|
543
|
+
event.sources = plan.engine.propagation_source_events
|
496
544
|
fire(event)
|
497
545
|
|
498
546
|
true
|
@@ -505,21 +553,31 @@ module Roby
|
|
505
553
|
def emit(*context)
|
506
554
|
check_emission_validity
|
507
555
|
|
556
|
+
# This test must not be done in #emit_without_propagation as the
|
557
|
+
# other ones: it is possible, using Distributed.update, to disable
|
558
|
+
# ownership tests, but that does not work if the test is in
|
559
|
+
# #emit_without_propagation
|
560
|
+
if !self_owned?
|
561
|
+
raise OwnershipError, "cannot emit an event we don't own. #{self} is owned by #{owners}"
|
562
|
+
end
|
563
|
+
|
508
564
|
context.compact!
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
565
|
+
engine = plan.engine
|
566
|
+
if engine.gathering?
|
567
|
+
engine.add_event_propagation(true, engine.propagation_sources, self, (context unless context.empty?), nil)
|
568
|
+
else
|
569
|
+
Roby.synchronize do
|
570
|
+
errors = engine.propagate_events do |initial_set|
|
571
|
+
engine.add_event_propagation(true, engine.propagation_sources, self, (context unless context.empty?), nil)
|
515
572
|
end
|
516
573
|
if errors.size == 1
|
517
574
|
e = errors.first.exception
|
518
|
-
raise e, e.message, e.backtrace
|
575
|
+
raise e.dup, e.message, Roby.filter_backtrace(e.backtrace)
|
519
576
|
elsif !errors.empty?
|
520
|
-
|
521
|
-
|
522
|
-
|
577
|
+
for e in errors
|
578
|
+
pp e.exception
|
579
|
+
end
|
580
|
+
raise "multiple exceptions"
|
523
581
|
end
|
524
582
|
end
|
525
583
|
end
|
@@ -528,8 +586,9 @@ module Roby
|
|
528
586
|
# Deprecated. Instead of using
|
529
587
|
# dest.emit_on(source)
|
530
588
|
# now use
|
531
|
-
# source.
|
589
|
+
# source.forward_to(dest)
|
532
590
|
def emit_on(generator, timespec = nil)
|
591
|
+
Roby.warn_deprecated "a.emit_on(b) has been replaced by b.forward_to(a)"
|
533
592
|
generator.forward(self, timespec)
|
534
593
|
self
|
535
594
|
end
|
@@ -558,15 +617,11 @@ module Roby
|
|
558
617
|
self.emit(yield(context))
|
559
618
|
end
|
560
619
|
else
|
561
|
-
ev.
|
620
|
+
ev.forward_to_once self
|
562
621
|
end
|
563
622
|
|
564
623
|
ev.if_unreachable(true) do |reason|
|
565
|
-
|
566
|
-
if ev.respond_to?(:task)
|
567
|
-
msg << "\n " << ev.task.history.map { |ev| "#{ev.time.to_hms} #{ev.symbol}: #{ev.context}" }.join("\n ")
|
568
|
-
end
|
569
|
-
emit_failed(UnreachableEvent.new(self, reason), msg)
|
624
|
+
emit_failed(UnreachableEvent.new(self, reason))
|
570
625
|
end
|
571
626
|
end
|
572
627
|
# For backwards compatibility. Use #achieve_with.
|
@@ -597,7 +652,7 @@ module Roby
|
|
597
652
|
#
|
598
653
|
# A reason string can be provided for debugging purposes
|
599
654
|
def postpone(generator, reason = nil)
|
600
|
-
generator.
|
655
|
+
generator.signals self
|
601
656
|
yield if block_given?
|
602
657
|
throw :postponed, [generator, reason]
|
603
658
|
end
|
@@ -673,7 +728,7 @@ module Roby
|
|
673
728
|
# by the given block
|
674
729
|
def filter(*new_context, &block)
|
675
730
|
filter = FilterGenerator.new(new_context, &block)
|
676
|
-
self.
|
731
|
+
self.signals(filter)
|
677
732
|
filter
|
678
733
|
end
|
679
734
|
|
@@ -682,7 +737,7 @@ module Roby
|
|
682
737
|
#
|
683
738
|
# source, ev, limit = (1..3).map { EventGenerator.new(true) }
|
684
739
|
# ev.until(limit).on { STDERR.puts "FIRED !!!" }
|
685
|
-
# source.
|
740
|
+
# source.signals ev
|
686
741
|
#
|
687
742
|
# Will do
|
688
743
|
#
|
@@ -702,6 +757,19 @@ module Roby
|
|
702
757
|
super
|
703
758
|
end
|
704
759
|
|
760
|
+
def added_child_object(child, relations, info) # :nodoc:
|
761
|
+
super if defined? super
|
762
|
+
if relations.include?(Roby::EventStructure::Precedence) && plan && plan.engine
|
763
|
+
plan.engine.event_ordering.clear
|
764
|
+
end
|
765
|
+
end
|
766
|
+
def removed_child_object(child, relations) # :nodoc:
|
767
|
+
super if defined? super
|
768
|
+
if relations.include?(Roby::EventStructure::Precedence) && plan && plan.engine
|
769
|
+
plan.engine.event_ordering.clear
|
770
|
+
end
|
771
|
+
end
|
772
|
+
|
705
773
|
@@event_gathering = Hash.new { |h, k| h[k] = ValueSet.new }
|
706
774
|
# If a generator in +events+ fires, add the fired event in +collection+
|
707
775
|
def self.gather_events(collection, events)
|
@@ -721,30 +789,28 @@ module Roby
|
|
721
789
|
# event generators +collection+ is listening for.
|
722
790
|
def self.event_gathering; @@event_gathering end
|
723
791
|
|
724
|
-
# This module is hooked in Roby::Plan to remove from the
|
725
|
-
# event_gathering sets the events that have been finalized
|
726
|
-
module FinalizedEventHook
|
727
|
-
def finalized_event(event)
|
728
|
-
super if defined? super
|
729
|
-
event.unreachable!
|
730
|
-
end
|
731
|
-
end
|
732
|
-
Roby::Plan.include FinalizedEventHook
|
733
|
-
|
734
792
|
attr_predicate :unreachable?
|
793
|
+
# If the event became unreachable, this holds the reason for its
|
794
|
+
# unreachability, if that reason is known. This reason is always an
|
795
|
+
# Event instance which represents the emission that triggered this
|
796
|
+
# unreachability.
|
797
|
+
attr_reader :unreachability_reason
|
735
798
|
|
736
799
|
# Called internally when the event becomes unreachable
|
737
|
-
def unreachable!(reason = nil)
|
800
|
+
def unreachable!(reason = nil, plan = self.plan)
|
738
801
|
return if @unreachable
|
739
802
|
@unreachable = true
|
803
|
+
@unreachability_reason = reason
|
740
804
|
|
741
805
|
EventGenerator.event_gathering.delete(self)
|
742
806
|
|
743
807
|
unreachable_handlers.each do |_, block|
|
744
808
|
begin
|
745
809
|
block.call(reason)
|
810
|
+
rescue LocalizedError => e
|
811
|
+
plan.engine.add_error(e)
|
746
812
|
rescue Exception => e
|
747
|
-
|
813
|
+
plan.engine.add_error(EventHandlerError.new(e, self))
|
748
814
|
end
|
749
815
|
end
|
750
816
|
unreachable_handlers.clear
|
@@ -935,8 +1001,8 @@ module Roby
|
|
935
1001
|
end
|
936
1002
|
|
937
1003
|
if source && limit
|
938
|
-
source.
|
939
|
-
limit.
|
1004
|
+
source.forward_to(self)
|
1005
|
+
limit.signals(self)
|
940
1006
|
end
|
941
1007
|
end
|
942
1008
|
end
|