roby 0.8.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (644) hide show
  1. checksums.yaml +7 -0
  2. data/.deep-cover.rb +3 -0
  3. data/.gitattributes +1 -0
  4. data/.gitignore +24 -0
  5. data/.simplecov +10 -0
  6. data/.travis.yml +17 -0
  7. data/.yardopts +4 -0
  8. data/Gemfile +15 -0
  9. data/README.md +11 -0
  10. data/Rakefile +47 -177
  11. data/benchmark/{alloc_misc.rb → attic/alloc_misc.rb} +2 -2
  12. data/benchmark/{discovery_latency.rb → attic/discovery_latency.rb} +19 -19
  13. data/benchmark/{garbage_collection.rb → attic/garbage_collection.rb} +9 -9
  14. data/benchmark/{genom.rb → attic/genom.rb} +0 -0
  15. data/benchmark/attic/transactions.rb +62 -0
  16. data/benchmark/plan_basic_operations.rb +28 -0
  17. data/benchmark/relations/graph.rb +63 -0
  18. data/benchmark/ruby/identity.rb +18 -0
  19. data/benchmark/ruby/set_intersect_vs_hash_merge.rb +39 -0
  20. data/benchmark/ruby/yield_vs_block.rb +35 -0
  21. data/benchmark/run +5 -0
  22. data/benchmark/synthetic_plan_modifications_with_transactions.rb +79 -0
  23. data/benchmark/transactions.rb +99 -51
  24. data/bin/roby +38 -197
  25. data/bin/roby-display +14 -0
  26. data/bin/roby-log +3 -176
  27. data/doc/guide/{src → attic}/abstraction/achieve_with.page +1 -1
  28. data/doc/guide/{src → attic}/abstraction/forwarding.page +1 -1
  29. data/doc/guide/{src → attic}/abstraction/hierarchy.page +1 -1
  30. data/doc/guide/{src → attic}/abstraction/index.page +1 -1
  31. data/doc/guide/{src → attic}/abstraction/task_models.page +1 -1
  32. data/doc/guide/{overview.rdoc → attic/cycle/api_overview.rdoc} +6 -1
  33. data/doc/guide/{src → attic}/cycle/cycle-overview.png +0 -0
  34. data/doc/guide/{src → attic}/cycle/cycle-overview.svg +0 -0
  35. data/doc/guide/attic/cycle/error_handling.page +98 -0
  36. data/doc/guide/{src → attic}/cycle/error_instantaneous_repair.png +0 -0
  37. data/doc/guide/{src → attic}/cycle/error_instantaneous_repair.svg +0 -0
  38. data/doc/guide/{src/cycle/error_handling.page → attic/cycle/error_sources.page} +46 -89
  39. data/doc/guide/{src → attic}/cycle/garbage_collection.page +1 -1
  40. data/doc/guide/{src → attic}/cycle/index.page +1 -1
  41. data/doc/guide/{src → attic}/cycle/propagation.page +11 -1
  42. data/doc/guide/{src → attic}/cycle/propagation_diamond.png +0 -0
  43. data/doc/guide/{src → attic}/cycle/propagation_diamond.svg +0 -0
  44. data/doc/guide/attic/plans/building_plans.page +89 -0
  45. data/doc/guide/attic/plans/code.page +192 -0
  46. data/doc/guide/{src/basics → attic/plans}/events.page +3 -4
  47. data/doc/guide/attic/plans/index.page +7 -0
  48. data/doc/guide/{plan_modifications.rdoc → attic/plans/plan_modifications.rdoc} +5 -3
  49. data/doc/guide/{src/basics → attic/plans}/plan_objects.page +2 -1
  50. data/doc/guide/attic/plans/querying_plans.page +5 -0
  51. data/doc/guide/{src/basics → attic/plans}/tasks.page +20 -20
  52. data/doc/guide/config.yaml +7 -4
  53. data/doc/guide/ext/extended_menu.rb +29 -0
  54. data/doc/guide/ext/init.rb +6 -0
  55. data/doc/guide/ext/rdoc_links.rb +7 -6
  56. data/doc/guide/src/advanced_concepts/history.page +5 -0
  57. data/doc/guide/src/advanced_concepts/index.page +11 -0
  58. data/doc/guide/src/advanced_concepts/recognizing_patterns.page +83 -0
  59. data/doc/guide/src/advanced_concepts/scheduling.page +87 -0
  60. data/doc/guide/src/advanced_concepts/transactions.page +5 -0
  61. data/doc/guide/src/advanced_concepts/unreachability.page +42 -0
  62. data/doc/guide/src/base.template +96 -0
  63. data/doc/guide/src/basics_shell_header.txt +5 -7
  64. data/doc/guide/src/building/action_coordination.page +96 -0
  65. data/doc/guide/src/building/actions.page +124 -0
  66. data/doc/guide/src/building/file_layout.page +71 -0
  67. data/doc/guide/src/building/index.page +50 -0
  68. data/doc/guide/src/building/patterns.page +86 -0
  69. data/doc/guide/src/building/patterns_forwarding.png +0 -0
  70. data/doc/guide/src/building/patterns_forwarding.svg +277 -0
  71. data/doc/guide/src/building/runtime.page +95 -0
  72. data/doc/guide/src/building/task_models.page +94 -0
  73. data/doc/guide/src/building/tasks.page +284 -0
  74. data/doc/guide/src/concepts/error_handling.page +100 -0
  75. data/doc/guide/src/concepts/exception_propagation.png +0 -0
  76. data/doc/guide/src/concepts/exception_propagation.svg +445 -0
  77. data/doc/guide/src/concepts/execution.page +85 -0
  78. data/doc/guide/src/concepts/execution.png +0 -0
  79. data/doc/guide/src/concepts/execution.svg +573 -0
  80. data/doc/guide/src/concepts/execution_cycle.png +0 -0
  81. data/doc/guide/src/concepts/garbage_collection.page +57 -0
  82. data/doc/guide/src/concepts/index.page +27 -0
  83. data/doc/guide/src/concepts/plans.page +101 -0
  84. data/doc/guide/src/concepts/policy.page +31 -0
  85. data/doc/guide/src/concepts/reactor.page +61 -0
  86. data/doc/guide/src/concepts/simple_plan_example.png +0 -0
  87. data/doc/guide/src/concepts/simple_plan_example.svg +376 -0
  88. data/doc/guide/src/default.template +9 -74
  89. data/doc/guide/src/event_relations/forward.page +71 -0
  90. data/doc/guide/src/event_relations/index.page +12 -0
  91. data/doc/guide/src/event_relations/scheduling_constraints.page +43 -0
  92. data/doc/guide/src/event_relations/signal.page +55 -0
  93. data/doc/guide/src/event_relations/temporal_constraints.page +77 -0
  94. data/doc/guide/src/htmldoc.metainfo +21 -8
  95. data/doc/guide/src/index.page +8 -3
  96. data/doc/guide/src/{introduction/install.page → installation/index.page} +37 -25
  97. data/doc/guide/src/installation/publications.page +14 -0
  98. data/doc/guide/src/{introduction → installation}/videos.page +14 -7
  99. data/doc/guide/src/interacting/index.page +16 -0
  100. data/doc/guide/src/interacting/run.page +33 -0
  101. data/doc/guide/src/interacting/shell.page +95 -0
  102. data/doc/guide/src/plugins/creating_plugins.page +72 -0
  103. data/doc/guide/src/plugins/index.page +27 -5
  104. data/doc/guide/src/plugins/{fault_tolerance.page → standard_plugins/fault_tolerance.page} +2 -2
  105. data/doc/guide/src/plugins/standard_plugins/index.page +11 -0
  106. data/doc/guide/src/plugins/{subsystems.page → standard_plugins/subsystems.page} +2 -2
  107. data/doc/guide/src/style_screen.css +687 -0
  108. data/doc/guide/src/task_relations/dependency.page +107 -0
  109. data/doc/guide/src/task_relations/executed_by.page +77 -0
  110. data/doc/guide/src/task_relations/index.page +12 -0
  111. data/doc/guide/src/task_relations/new_relations.page +119 -0
  112. data/doc/guide/src/task_relations/planned_by.page +46 -0
  113. data/doc/guide/src/tutorial/app.page +117 -0
  114. data/doc/guide/src/{basics → tutorial}/code_examples.page +6 -5
  115. data/doc/guide/src/{basics → tutorial}/dry.page +15 -15
  116. data/doc/guide/src/{basics → tutorial}/errors.page +43 -68
  117. data/doc/guide/src/tutorial/events.page +195 -0
  118. data/doc/guide/src/{basics → tutorial}/hierarchy.page +53 -52
  119. data/doc/guide/src/tutorial/index.page +13 -0
  120. data/doc/guide/src/tutorial/log_replay/goForward_1.png +0 -0
  121. data/doc/guide/src/tutorial/log_replay/goForward_2.png +0 -0
  122. data/doc/guide/src/tutorial/log_replay/goForward_3.png +0 -0
  123. data/doc/guide/src/{basics → tutorial}/log_replay/goForward_4.png +0 -0
  124. data/doc/guide/src/tutorial/log_replay/goForward_5.png +0 -0
  125. data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_1.png +0 -0
  126. data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_2.png +0 -0
  127. data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_3.png +0 -0
  128. data/doc/guide/src/tutorial/log_replay/moveto_code_error.png +0 -0
  129. data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_1.png +0 -0
  130. data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_2.png +0 -0
  131. data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_3.png +0 -0
  132. data/doc/guide/src/tutorial/log_replay/plan_repair_4.png +0 -0
  133. data/doc/guide/src/tutorial/log_replay/roby_log_main_window.png +0 -0
  134. data/doc/guide/src/{basics → tutorial}/log_replay/roby_log_relation_window.png +0 -0
  135. data/doc/guide/src/{basics → tutorial}/log_replay/roby_replay_event_representation.png +0 -0
  136. data/doc/guide/src/tutorial/relations_display.page +153 -0
  137. data/doc/guide/src/{basics → tutorial}/roby_cycle_overview.png +0 -0
  138. data/doc/guide/src/tutorial/shell.page +121 -0
  139. data/doc/guide/src/{basics → tutorial}/summary.page +1 -1
  140. data/doc/guide/src/tutorial/tasks.page +374 -0
  141. data/lib/roby.rb +102 -47
  142. data/lib/roby/actions.rb +17 -0
  143. data/lib/roby/actions/action.rb +80 -0
  144. data/lib/roby/actions/interface.rb +45 -0
  145. data/lib/roby/actions/library.rb +23 -0
  146. data/lib/roby/actions/models/action.rb +224 -0
  147. data/lib/roby/actions/models/coordination_action.rb +58 -0
  148. data/lib/roby/actions/models/interface.rb +22 -0
  149. data/lib/roby/actions/models/interface_base.rb +294 -0
  150. data/lib/roby/actions/models/library.rb +12 -0
  151. data/lib/roby/actions/models/method_action.rb +90 -0
  152. data/lib/roby/actions/task.rb +114 -0
  153. data/lib/roby/and_generator.rb +125 -0
  154. data/lib/roby/app.rb +2795 -829
  155. data/lib/roby/app/autotest_console_reporter.rb +138 -0
  156. data/lib/roby/app/base.rb +21 -0
  157. data/lib/roby/app/cucumber.rb +2 -0
  158. data/lib/roby/app/cucumber/controller.rb +439 -0
  159. data/lib/roby/app/cucumber/helpers.rb +280 -0
  160. data/lib/roby/app/cucumber/world.rb +32 -0
  161. data/lib/roby/app/debug.rb +136 -0
  162. data/lib/roby/app/gen.rb +2 -0
  163. data/lib/roby/app/rake.rb +178 -38
  164. data/lib/roby/app/robot_config.rb +9 -0
  165. data/lib/roby/app/robot_names.rb +115 -0
  166. data/lib/roby/app/run.rb +3 -2
  167. data/lib/roby/app/scripts.rb +72 -0
  168. data/lib/roby/app/scripts/autotest.rb +173 -0
  169. data/lib/roby/app/scripts/display.rb +2 -0
  170. data/lib/roby/app/scripts/restart.rb +52 -0
  171. data/lib/roby/app/scripts/results.rb +17 -8
  172. data/lib/roby/app/scripts/run.rb +155 -24
  173. data/lib/roby/app/scripts/shell.rb +147 -62
  174. data/lib/roby/app/scripts/test.rb +107 -22
  175. data/lib/roby/app/test_reporter.rb +74 -0
  176. data/lib/roby/app/test_server.rb +159 -0
  177. data/lib/roby/app/vagrant.rb +47 -0
  178. data/lib/roby/backports.rb +16 -0
  179. data/lib/roby/cli/display.rb +190 -0
  180. data/lib/roby/cli/exceptions.rb +17 -0
  181. data/lib/roby/cli/gen/actions/class.rb +5 -0
  182. data/lib/roby/cli/gen/actions/test.rb +6 -0
  183. data/lib/roby/cli/gen/app/.yardopts +6 -0
  184. data/lib/roby/cli/gen/app/README.md +28 -0
  185. data/lib/roby/cli/gen/app/Rakefile +15 -0
  186. data/{app → lib/roby/cli/gen/app}/config/app.yml +29 -39
  187. data/lib/roby/cli/gen/app/models/.gitattributes +1 -0
  188. data/{app → lib/roby/cli/gen/app/scripts}/controllers/.gitattributes +0 -0
  189. data/{app/data/.gitattributes → lib/roby/cli/gen/app/test/.gitignore} +0 -0
  190. data/lib/roby/cli/gen/class/class.rb +6 -0
  191. data/lib/roby/cli/gen/class/test.rb +7 -0
  192. data/lib/roby/cli/gen/helpers.rb +203 -0
  193. data/lib/roby/cli/gen/module/module.rb +5 -0
  194. data/lib/roby/cli/gen/module/test.rb +6 -0
  195. data/lib/roby/cli/gen/roby_app/config/init.rb +17 -0
  196. data/lib/roby/cli/gen/roby_app/config/robots/robot.rb +40 -0
  197. data/lib/roby/cli/gen/task/class.rb +44 -0
  198. data/lib/roby/cli/gen/task/test.rb +6 -0
  199. data/lib/roby/cli/gen_main.rb +120 -0
  200. data/lib/roby/cli/log.rb +276 -0
  201. data/lib/roby/cli/log/flamegraph.html +499 -0
  202. data/lib/roby/cli/log/flamegraph_renderer.rb +88 -0
  203. data/lib/roby/cli/main.rb +153 -0
  204. data/lib/roby/coordination.rb +60 -0
  205. data/lib/roby/coordination/action_script.rb +25 -0
  206. data/lib/roby/coordination/action_state_machine.rb +125 -0
  207. data/lib/roby/coordination/actions.rb +106 -0
  208. data/lib/roby/coordination/base.rb +145 -0
  209. data/lib/roby/coordination/calculus.rb +40 -0
  210. data/lib/roby/coordination/child.rb +28 -0
  211. data/lib/roby/coordination/event.rb +29 -0
  212. data/lib/roby/coordination/fault_handler.rb +25 -0
  213. data/lib/roby/coordination/fault_handling_task.rb +13 -0
  214. data/lib/roby/coordination/fault_response_table.rb +110 -0
  215. data/lib/roby/coordination/models/action_script.rb +64 -0
  216. data/lib/roby/coordination/models/action_state_machine.rb +224 -0
  217. data/lib/roby/coordination/models/actions.rb +191 -0
  218. data/lib/roby/coordination/models/arguments.rb +55 -0
  219. data/lib/roby/coordination/models/base.rb +176 -0
  220. data/lib/roby/coordination/models/capture.rb +86 -0
  221. data/lib/roby/coordination/models/child.rb +35 -0
  222. data/lib/roby/coordination/models/event.rb +41 -0
  223. data/lib/roby/coordination/models/exceptions.rb +42 -0
  224. data/lib/roby/coordination/models/fault_handler.rb +219 -0
  225. data/lib/roby/coordination/models/fault_response_table.rb +77 -0
  226. data/lib/roby/coordination/models/root.rb +22 -0
  227. data/lib/roby/coordination/models/script.rb +283 -0
  228. data/lib/roby/coordination/models/task.rb +184 -0
  229. data/lib/roby/coordination/models/task_from_action.rb +50 -0
  230. data/lib/roby/coordination/models/task_from_as_plan.rb +33 -0
  231. data/lib/roby/coordination/models/task_from_instanciation_object.rb +31 -0
  232. data/lib/roby/coordination/models/task_from_variable.rb +27 -0
  233. data/lib/roby/coordination/models/task_with_dependencies.rb +48 -0
  234. data/lib/roby/coordination/models/variable.rb +32 -0
  235. data/lib/roby/coordination/script.rb +200 -0
  236. data/lib/roby/coordination/script_instruction.rb +12 -0
  237. data/lib/roby/coordination/task.rb +45 -0
  238. data/lib/roby/coordination/task_base.rb +69 -0
  239. data/lib/roby/coordination/task_script.rb +293 -0
  240. data/lib/roby/coordination/task_state_machine.rb +308 -0
  241. data/lib/roby/decision_control.rb +33 -21
  242. data/lib/roby/distributed_object.rb +76 -0
  243. data/lib/roby/droby.rb +17 -0
  244. data/lib/roby/droby/droby_id.rb +6 -0
  245. data/lib/roby/droby/enable.rb +153 -0
  246. data/lib/roby/droby/event_logger.rb +189 -0
  247. data/lib/roby/droby/event_logging.rb +57 -0
  248. data/lib/roby/droby/exceptions.rb +14 -0
  249. data/lib/roby/droby/identifiable.rb +22 -0
  250. data/lib/roby/droby/logfile.rb +141 -0
  251. data/lib/roby/droby/logfile/client.rb +176 -0
  252. data/lib/roby/droby/logfile/file_format.md +97 -0
  253. data/lib/roby/droby/logfile/index.rb +117 -0
  254. data/lib/roby/droby/logfile/reader.rb +139 -0
  255. data/lib/roby/droby/logfile/server.rb +199 -0
  256. data/lib/roby/droby/logfile/writer.rb +114 -0
  257. data/lib/roby/droby/marshal.rb +264 -0
  258. data/lib/roby/droby/marshallable.rb +12 -0
  259. data/lib/roby/droby/null_event_logger.rb +25 -0
  260. data/lib/roby/droby/object_manager.rb +205 -0
  261. data/lib/roby/droby/peer_id.rb +6 -0
  262. data/lib/roby/droby/plan_rebuilder.rb +373 -0
  263. data/lib/roby/droby/rebuilt_plan.rb +160 -0
  264. data/lib/roby/droby/remote_droby_id.rb +6 -0
  265. data/lib/roby/droby/timepoints.rb +205 -0
  266. data/lib/roby/droby/timepoints_ctf.metadata.erb +101 -0
  267. data/lib/roby/droby/timepoints_ctf.rb +125 -0
  268. data/lib/roby/droby/v5.rb +14 -0
  269. data/lib/roby/droby/v5/builtin.rb +120 -0
  270. data/lib/roby/droby/v5/droby_class.rb +45 -0
  271. data/lib/roby/droby/v5/droby_constant.rb +81 -0
  272. data/lib/roby/droby/v5/droby_dump.rb +1026 -0
  273. data/lib/roby/droby/v5/droby_id.rb +44 -0
  274. data/lib/roby/droby/v5/droby_model.rb +82 -0
  275. data/lib/roby/droby/v5/peer_id.rb +10 -0
  276. data/lib/roby/droby/v5/remote_droby_id.rb +42 -0
  277. data/lib/roby/event.rb +79 -957
  278. data/lib/roby/event_constraints.rb +835 -0
  279. data/lib/roby/event_generator.rb +1047 -0
  280. data/lib/roby/event_structure/causal_link.rb +6 -0
  281. data/lib/roby/event_structure/forwarding.rb +6 -0
  282. data/lib/roby/event_structure/precedence.rb +7 -0
  283. data/lib/roby/event_structure/signal.rb +8 -0
  284. data/lib/roby/event_structure/temporal_constraints.rb +640 -0
  285. data/lib/roby/exceptions.rb +446 -152
  286. data/lib/roby/executable_plan.rb +549 -0
  287. data/lib/roby/execution_engine.rb +1997 -950
  288. data/lib/roby/filter_generator.rb +26 -0
  289. data/lib/roby/gui/chronicle_view.rb +225 -0
  290. data/lib/roby/gui/chronicle_widget.rb +925 -0
  291. data/lib/roby/gui/dot_id.rb +11 -0
  292. data/lib/roby/gui/exception_view.rb +44 -0
  293. data/lib/roby/gui/log_display.rb +273 -0
  294. data/lib/roby/gui/model_views.rb +2 -0
  295. data/lib/roby/gui/model_views/action_interface.rb +53 -0
  296. data/lib/roby/gui/model_views/task.rb +47 -0
  297. data/lib/roby/gui/model_views/task.rhtml +41 -0
  298. data/lib/roby/gui/object_info_view.rb +89 -0
  299. data/lib/roby/gui/plan_dot_layout.rb +427 -0
  300. data/lib/roby/gui/plan_rebuilder_widget.rb +357 -0
  301. data/lib/roby/gui/qt4_toMSecsSinceEpoch.rb +8 -0
  302. data/lib/roby/gui/relations_view.rb +278 -0
  303. data/lib/roby/gui/relations_view/relations.ui +139 -0
  304. data/lib/roby/gui/relations_view/relations_canvas.rb +1088 -0
  305. data/lib/roby/gui/relations_view/relations_config.rb +292 -0
  306. data/lib/roby/gui/relations_view/relations_view.ui +53 -0
  307. data/lib/roby/gui/scheduler_view.css +24 -0
  308. data/lib/roby/gui/scheduler_view.rb +46 -0
  309. data/lib/roby/gui/scheduler_view.rhtml +53 -0
  310. data/lib/roby/gui/stepping.rb +93 -0
  311. data/lib/roby/gui/stepping.ui +181 -0
  312. data/lib/roby/gui/styles.rb +81 -0
  313. data/lib/roby/gui/task_display_configuration.rb +42 -0
  314. data/lib/roby/gui/task_state_at.rb +38 -0
  315. data/lib/roby/hooks.rb +26 -0
  316. data/lib/roby/interface.rb +136 -469
  317. data/lib/roby/interface/async.rb +20 -0
  318. data/lib/roby/interface/async/action_monitor.rb +188 -0
  319. data/lib/roby/interface/async/interface.rb +498 -0
  320. data/lib/roby/interface/async/job_monitor.rb +213 -0
  321. data/lib/roby/interface/async/log.rb +238 -0
  322. data/lib/roby/interface/async/new_job_listener.rb +79 -0
  323. data/lib/roby/interface/async/ui_connector.rb +183 -0
  324. data/lib/roby/interface/client.rb +553 -0
  325. data/lib/roby/interface/command.rb +24 -0
  326. data/lib/roby/interface/command_argument.rb +16 -0
  327. data/lib/roby/interface/command_library.rb +92 -0
  328. data/lib/roby/interface/droby_channel.rb +174 -0
  329. data/lib/roby/interface/exceptions.rb +22 -0
  330. data/lib/roby/interface/interface.rb +655 -0
  331. data/lib/roby/interface/job.rb +47 -0
  332. data/lib/roby/interface/rest.rb +10 -0
  333. data/lib/roby/interface/rest/api.rb +29 -0
  334. data/lib/roby/interface/rest/helpers.rb +24 -0
  335. data/lib/roby/interface/rest/server.rb +212 -0
  336. data/lib/roby/interface/server.rb +154 -0
  337. data/lib/roby/interface/shell_client.rb +468 -0
  338. data/lib/roby/interface/shell_subcommand.rb +24 -0
  339. data/lib/roby/interface/subcommand_client.rb +35 -0
  340. data/lib/roby/interface/tcp.rb +168 -0
  341. data/lib/roby/models/arguments.rb +112 -0
  342. data/lib/roby/models/plan_object.rb +83 -0
  343. data/lib/roby/models/task.rb +835 -0
  344. data/lib/roby/models/task_event.rb +62 -0
  345. data/lib/roby/models/task_service.rb +78 -0
  346. data/lib/roby/or_generator.rb +88 -0
  347. data/lib/roby/plan.rb +1751 -864
  348. data/lib/roby/plan_object.rb +611 -0
  349. data/lib/roby/plan_service.rb +200 -0
  350. data/lib/roby/promise.rb +332 -0
  351. data/lib/roby/queries.rb +23 -0
  352. data/lib/roby/queries/and_matcher.rb +32 -0
  353. data/lib/roby/queries/any.rb +27 -0
  354. data/lib/roby/queries/code_error_matcher.rb +58 -0
  355. data/lib/roby/queries/event_generator_matcher.rb +9 -0
  356. data/lib/roby/queries/execution_exception_matcher.rb +165 -0
  357. data/lib/roby/queries/index.rb +165 -0
  358. data/lib/roby/queries/localized_error_matcher.rb +149 -0
  359. data/lib/roby/queries/matcher_base.rb +107 -0
  360. data/lib/roby/queries/none.rb +27 -0
  361. data/lib/roby/queries/not_matcher.rb +30 -0
  362. data/lib/roby/queries/op_matcher.rb +8 -0
  363. data/lib/roby/queries/or_matcher.rb +30 -0
  364. data/lib/roby/queries/plan_object_matcher.rb +363 -0
  365. data/lib/roby/queries/query.rb +188 -0
  366. data/lib/roby/queries/task_event_generator_matcher.rb +86 -0
  367. data/lib/roby/queries/task_matcher.rb +344 -0
  368. data/lib/roby/relations.rb +42 -678
  369. data/lib/roby/relations/bidirectional_directed_adjacency_graph.rb +492 -0
  370. data/lib/roby/relations/directed_relation_support.rb +268 -0
  371. data/lib/roby/relations/event_relation_graph.rb +19 -0
  372. data/lib/roby/relations/fork_merge_visitor.rb +154 -0
  373. data/lib/roby/relations/graph.rb +533 -0
  374. data/lib/roby/relations/models/directed_relation_support.rb +11 -0
  375. data/lib/roby/relations/models/graph.rb +75 -0
  376. data/lib/roby/relations/models/task_relation_graph.rb +18 -0
  377. data/lib/roby/relations/space.rb +380 -0
  378. data/lib/roby/relations/task_relation_graph.rb +20 -0
  379. data/lib/roby/robot.rb +85 -38
  380. data/lib/roby/schedulers/basic.rb +155 -25
  381. data/lib/roby/schedulers/null.rb +20 -0
  382. data/lib/roby/schedulers/reporting.rb +31 -0
  383. data/lib/roby/schedulers/state.rb +129 -0
  384. data/lib/roby/schedulers/temporal.rb +91 -0
  385. data/lib/roby/singletons.rb +87 -0
  386. data/lib/roby/standalone.rb +4 -2
  387. data/lib/roby/standard_errors.rb +405 -82
  388. data/lib/roby/state.rb +6 -3
  389. data/lib/roby/state/conf_model.rb +5 -0
  390. data/lib/roby/state/events.rb +181 -95
  391. data/lib/roby/state/goal_model.rb +77 -0
  392. data/lib/roby/state/open_struct.rb +591 -0
  393. data/lib/roby/state/open_struct_model.rb +68 -0
  394. data/lib/roby/state/pos.rb +45 -45
  395. data/lib/roby/state/shapes.rb +11 -11
  396. data/lib/roby/state/state_model.rb +303 -0
  397. data/lib/roby/state/task.rb +43 -0
  398. data/lib/roby/support.rb +88 -148
  399. data/lib/roby/task.rb +1361 -1750
  400. data/lib/roby/task_arguments.rb +428 -0
  401. data/lib/roby/task_event.rb +127 -0
  402. data/lib/roby/task_event_generator.rb +337 -0
  403. data/lib/roby/task_service.rb +6 -0
  404. data/lib/roby/task_structure/conflicts.rb +104 -0
  405. data/lib/roby/task_structure/dependency.rb +932 -0
  406. data/lib/roby/task_structure/error_handling.rb +118 -0
  407. data/lib/roby/task_structure/executed_by.rb +234 -0
  408. data/lib/roby/task_structure/planned_by.rb +90 -0
  409. data/lib/roby/tasks/aggregator.rb +37 -0
  410. data/lib/roby/tasks/external_process.rb +275 -0
  411. data/lib/roby/tasks/group.rb +27 -0
  412. data/lib/roby/tasks/null.rb +19 -0
  413. data/lib/roby/tasks/parallel.rb +43 -0
  414. data/lib/roby/tasks/sequence.rb +88 -0
  415. data/lib/roby/tasks/simple.rb +21 -0
  416. data/lib/roby/{thread_task.rb → tasks/thread.rb} +50 -24
  417. data/lib/roby/tasks/timeout.rb +17 -0
  418. data/lib/roby/tasks/virtual.rb +55 -0
  419. data/lib/roby/template_plan.rb +7 -0
  420. data/lib/roby/test/aruba_minitest.rb +74 -0
  421. data/lib/roby/test/assertion.rb +16 -0
  422. data/lib/roby/test/assertions.rb +490 -0
  423. data/lib/roby/test/common.rb +368 -591
  424. data/lib/roby/test/dsl.rb +149 -0
  425. data/lib/roby/test/error.rb +18 -0
  426. data/lib/roby/test/event_reporter.rb +83 -0
  427. data/lib/roby/test/execution_expectations.rb +1134 -0
  428. data/lib/roby/test/expect_execution.rb +151 -0
  429. data/lib/roby/test/minitest_helpers.rb +166 -0
  430. data/lib/roby/test/roby_app_helpers.rb +200 -0
  431. data/lib/roby/test/run_planners.rb +155 -0
  432. data/lib/roby/test/self.rb +112 -0
  433. data/lib/roby/test/spec.rb +198 -0
  434. data/lib/roby/test/tasks/empty_task.rb +4 -4
  435. data/lib/roby/test/tasks/goto.rb +28 -27
  436. data/lib/roby/test/teardown_plans.rb +100 -0
  437. data/lib/roby/test/testcase.rb +239 -307
  438. data/lib/roby/test/tools.rb +159 -155
  439. data/lib/roby/test/validate_state_machine.rb +75 -0
  440. data/lib/roby/transaction.rb +1125 -0
  441. data/lib/roby/transaction/event_generator_proxy.rb +63 -0
  442. data/lib/roby/transaction/plan_object_proxy.rb +99 -0
  443. data/lib/roby/transaction/plan_service_proxy.rb +43 -0
  444. data/lib/roby/transaction/proxying.rb +120 -0
  445. data/lib/roby/transaction/task_event_generator_proxy.rb +19 -0
  446. data/lib/roby/transaction/task_proxy.rb +135 -0
  447. data/lib/roby/until_generator.rb +30 -0
  448. data/lib/roby/version.rb +5 -0
  449. data/lib/roby/yard.rb +169 -0
  450. data/lib/yard-roby.rb +1 -0
  451. data/manifest.xml +32 -6
  452. data/roby.gemspec +59 -0
  453. metadata +788 -587
  454. data/Manifest.txt +0 -321
  455. data/NOTES +0 -4
  456. data/README.txt +0 -166
  457. data/TODO.txt +0 -146
  458. data/app/README.txt +0 -24
  459. data/app/Rakefile +0 -8
  460. data/app/config/ROBOT.rb +0 -5
  461. data/app/config/init.rb +0 -33
  462. data/app/config/roby.yml +0 -3
  463. data/app/controllers/ROBOT.rb +0 -2
  464. data/app/planners/ROBOT/main.rb +0 -6
  465. data/app/planners/main.rb +0 -5
  466. data/app/scripts/distributed +0 -3
  467. data/app/scripts/generate/bookmarks +0 -3
  468. data/app/scripts/replay +0 -3
  469. data/app/scripts/results +0 -3
  470. data/app/scripts/run +0 -3
  471. data/app/scripts/server +0 -3
  472. data/app/scripts/shell +0 -3
  473. data/app/scripts/test +0 -3
  474. data/app/tasks/.gitattributes +0 -0
  475. data/app/tasks/ROBOT/.gitattributes +0 -0
  476. data/bin/roby-shell +0 -25
  477. data/doc/guide/src/basics/app.page +0 -139
  478. data/doc/guide/src/basics/index.page +0 -11
  479. data/doc/guide/src/basics/log_replay/goForward_1.png +0 -0
  480. data/doc/guide/src/basics/log_replay/goForward_2.png +0 -0
  481. data/doc/guide/src/basics/log_replay/goForward_3.png +0 -0
  482. data/doc/guide/src/basics/log_replay/goForward_5.png +0 -0
  483. data/doc/guide/src/basics/log_replay/plan_repair_4.png +0 -0
  484. data/doc/guide/src/basics/log_replay/roby_log_main_window.png +0 -0
  485. data/doc/guide/src/basics/relations_display.page +0 -203
  486. data/doc/guide/src/basics/shell.page +0 -102
  487. data/doc/guide/src/default.css +0 -319
  488. data/doc/guide/src/introduction/index.page +0 -29
  489. data/doc/guide/src/introduction/publications.page +0 -14
  490. data/doc/guide/src/relations/dependency.page +0 -89
  491. data/doc/guide/src/relations/index.page +0 -12
  492. data/ext/droby/dump.cc +0 -175
  493. data/ext/droby/extconf.rb +0 -3
  494. data/ext/graph/algorithm.cc +0 -746
  495. data/ext/graph/extconf.rb +0 -7
  496. data/ext/graph/graph.cc +0 -575
  497. data/ext/graph/graph.hh +0 -183
  498. data/ext/graph/iterator_sequence.hh +0 -102
  499. data/ext/graph/undirected_dfs.hh +0 -226
  500. data/ext/graph/undirected_graph.hh +0 -421
  501. data/lib/roby/app/scripts/generate/bookmarks.rb +0 -162
  502. data/lib/roby/app/scripts/replay.rb +0 -31
  503. data/lib/roby/app/scripts/server.rb +0 -18
  504. data/lib/roby/basic_object.rb +0 -151
  505. data/lib/roby/config.rb +0 -14
  506. data/lib/roby/distributed.rb +0 -36
  507. data/lib/roby/distributed/base.rb +0 -448
  508. data/lib/roby/distributed/communication.rb +0 -875
  509. data/lib/roby/distributed/connection_space.rb +0 -616
  510. data/lib/roby/distributed/distributed_object.rb +0 -206
  511. data/lib/roby/distributed/drb.rb +0 -62
  512. data/lib/roby/distributed/notifications.rb +0 -531
  513. data/lib/roby/distributed/peer.rb +0 -555
  514. data/lib/roby/distributed/protocol.rb +0 -529
  515. data/lib/roby/distributed/proxy.rb +0 -343
  516. data/lib/roby/distributed/subscription.rb +0 -311
  517. data/lib/roby/distributed/transaction.rb +0 -498
  518. data/lib/roby/external_process_task.rb +0 -225
  519. data/lib/roby/graph.rb +0 -160
  520. data/lib/roby/log.rb +0 -3
  521. data/lib/roby/log/chronicle.rb +0 -303
  522. data/lib/roby/log/console.rb +0 -74
  523. data/lib/roby/log/data_stream.rb +0 -275
  524. data/lib/roby/log/dot.rb +0 -279
  525. data/lib/roby/log/event_stream.rb +0 -161
  526. data/lib/roby/log/file.rb +0 -396
  527. data/lib/roby/log/gui/basic_display.ui +0 -83
  528. data/lib/roby/log/gui/basic_display_ui.rb +0 -89
  529. data/lib/roby/log/gui/chronicle.rb +0 -26
  530. data/lib/roby/log/gui/chronicle_view.rb +0 -40
  531. data/lib/roby/log/gui/chronicle_view.ui +0 -70
  532. data/lib/roby/log/gui/chronicle_view_ui.rb +0 -90
  533. data/lib/roby/log/gui/data_displays.rb +0 -171
  534. data/lib/roby/log/gui/data_displays.ui +0 -155
  535. data/lib/roby/log/gui/data_displays_ui.rb +0 -146
  536. data/lib/roby/log/gui/notifications.rb +0 -26
  537. data/lib/roby/log/gui/relations.rb +0 -269
  538. data/lib/roby/log/gui/relations.ui +0 -123
  539. data/lib/roby/log/gui/relations_ui.rb +0 -120
  540. data/lib/roby/log/gui/relations_view.rb +0 -185
  541. data/lib/roby/log/gui/relations_view.ui +0 -149
  542. data/lib/roby/log/gui/relations_view_ui.rb +0 -144
  543. data/lib/roby/log/gui/replay.rb +0 -366
  544. data/lib/roby/log/gui/replay_controls.rb +0 -206
  545. data/lib/roby/log/gui/replay_controls.ui +0 -282
  546. data/lib/roby/log/gui/replay_controls_ui.rb +0 -249
  547. data/lib/roby/log/gui/runtime.rb +0 -130
  548. data/lib/roby/log/hooks.rb +0 -186
  549. data/lib/roby/log/logger.rb +0 -203
  550. data/lib/roby/log/notifications.rb +0 -244
  551. data/lib/roby/log/plan_rebuilder.rb +0 -468
  552. data/lib/roby/log/relations.rb +0 -1084
  553. data/lib/roby/log/server.rb +0 -547
  554. data/lib/roby/log/sqlite.rb +0 -47
  555. data/lib/roby/log/timings.rb +0 -233
  556. data/lib/roby/plan-object.rb +0 -371
  557. data/lib/roby/planning.rb +0 -13
  558. data/lib/roby/planning/loops.rb +0 -309
  559. data/lib/roby/planning/model.rb +0 -1012
  560. data/lib/roby/planning/task.rb +0 -180
  561. data/lib/roby/query.rb +0 -655
  562. data/lib/roby/relations/conflicts.rb +0 -67
  563. data/lib/roby/relations/dependency.rb +0 -358
  564. data/lib/roby/relations/ensured.rb +0 -19
  565. data/lib/roby/relations/error_handling.rb +0 -22
  566. data/lib/roby/relations/events.rb +0 -7
  567. data/lib/roby/relations/executed_by.rb +0 -208
  568. data/lib/roby/relations/influence.rb +0 -10
  569. data/lib/roby/relations/planned_by.rb +0 -63
  570. data/lib/roby/state/information.rb +0 -55
  571. data/lib/roby/state/state.rb +0 -367
  572. data/lib/roby/task-operations.rb +0 -186
  573. data/lib/roby/task_index.rb +0 -80
  574. data/lib/roby/test/distributed.rb +0 -230
  575. data/lib/roby/test/tasks/simple_task.rb +0 -23
  576. data/lib/roby/transactions.rb +0 -507
  577. data/lib/roby/transactions/proxy.rb +0 -325
  578. data/plugins/fault_injection/History.txt +0 -4
  579. data/plugins/fault_injection/README.txt +0 -34
  580. data/plugins/fault_injection/Rakefile +0 -12
  581. data/plugins/fault_injection/TODO.txt +0 -0
  582. data/plugins/fault_injection/app.rb +0 -52
  583. data/plugins/fault_injection/fault_injection.rb +0 -89
  584. data/plugins/fault_injection/test/test_fault_injection.rb +0 -78
  585. data/plugins/subsystems/README.txt +0 -37
  586. data/plugins/subsystems/Rakefile +0 -13
  587. data/plugins/subsystems/app.rb +0 -182
  588. data/plugins/subsystems/test/app/README +0 -24
  589. data/plugins/subsystems/test/app/Rakefile +0 -8
  590. data/plugins/subsystems/test/app/config/app.yml +0 -71
  591. data/plugins/subsystems/test/app/config/init.rb +0 -12
  592. data/plugins/subsystems/test/app/config/roby.yml +0 -3
  593. data/plugins/subsystems/test/app/planners/main.rb +0 -20
  594. data/plugins/subsystems/test/app/scripts/distributed +0 -3
  595. data/plugins/subsystems/test/app/scripts/replay +0 -3
  596. data/plugins/subsystems/test/app/scripts/results +0 -3
  597. data/plugins/subsystems/test/app/scripts/run +0 -3
  598. data/plugins/subsystems/test/app/scripts/server +0 -3
  599. data/plugins/subsystems/test/app/scripts/shell +0 -3
  600. data/plugins/subsystems/test/app/scripts/test +0 -3
  601. data/plugins/subsystems/test/app/tasks/services.rb +0 -15
  602. data/plugins/subsystems/test/test_subsystems.rb +0 -78
  603. data/test/distributed/test_communication.rb +0 -195
  604. data/test/distributed/test_connection.rb +0 -284
  605. data/test/distributed/test_execution.rb +0 -378
  606. data/test/distributed/test_mixed_plan.rb +0 -341
  607. data/test/distributed/test_plan_notifications.rb +0 -238
  608. data/test/distributed/test_protocol.rb +0 -525
  609. data/test/distributed/test_query.rb +0 -106
  610. data/test/distributed/test_remote_plan.rb +0 -491
  611. data/test/distributed/test_transaction.rb +0 -466
  612. data/test/mockups/external_process +0 -28
  613. data/test/mockups/tasks.rb +0 -27
  614. data/test/planning/test_loops.rb +0 -432
  615. data/test/planning/test_model.rb +0 -427
  616. data/test/planning/test_task.rb +0 -126
  617. data/test/relations/test_conflicts.rb +0 -42
  618. data/test/relations/test_dependency.rb +0 -324
  619. data/test/relations/test_ensured.rb +0 -38
  620. data/test/relations/test_executed_by.rb +0 -224
  621. data/test/relations/test_planned_by.rb +0 -56
  622. data/test/suite_core.rb +0 -29
  623. data/test/suite_distributed.rb +0 -10
  624. data/test/suite_planning.rb +0 -4
  625. data/test/suite_relations.rb +0 -8
  626. data/test/tasks/test_external_process.rb +0 -126
  627. data/test/tasks/test_thread_task.rb +0 -70
  628. data/test/test_bgl.rb +0 -528
  629. data/test/test_event.rb +0 -969
  630. data/test/test_exceptions.rb +0 -591
  631. data/test/test_execution_engine.rb +0 -987
  632. data/test/test_gui.rb +0 -20
  633. data/test/test_interface.rb +0 -43
  634. data/test/test_log.rb +0 -125
  635. data/test/test_log_server.rb +0 -133
  636. data/test/test_plan.rb +0 -418
  637. data/test/test_query.rb +0 -424
  638. data/test/test_relations.rb +0 -260
  639. data/test/test_state.rb +0 -432
  640. data/test/test_support.rb +0 -16
  641. data/test/test_task.rb +0 -1181
  642. data/test/test_testcase.rb +0 -138
  643. data/test/test_transactions.rb +0 -610
  644. data/test/test_transactions_proxy.rb +0 -216
@@ -0,0 +1,44 @@
1
+ module Roby
2
+ module DRoby
3
+ module V5
4
+ # These objects are used in distributed Roby to identify objects across
5
+ # the various Roby instances
6
+ class DRobyID
7
+ # The object ID
8
+ attr_reader :id
9
+
10
+ def initialize(id)
11
+ @id = id
12
+ @hash = id.hash
13
+ end
14
+
15
+ def ==(other) # :nodoc:
16
+ other.kind_of?(DRobyID) && other.id == id
17
+ end
18
+
19
+ alias :eql? :==
20
+ attr_reader :hash
21
+
22
+ def to_s
23
+ "#<DRobyID:#{id}>"
24
+ end
25
+ def inspect
26
+ to_s
27
+ end
28
+ def pretty_print(pp)
29
+ pp.text to_s
30
+ end
31
+
32
+ def self.droby_id_allocator
33
+ @droby_id_allocator
34
+ end
35
+ @droby_id_allocator = Concurrent::AtomicFixnum.new
36
+
37
+ def self.allocate
38
+ DRobyID.new(droby_id_allocator.increment)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+
@@ -0,0 +1,82 @@
1
+ module Roby
2
+ module DRoby
3
+ module V5
4
+ class DRobyModel
5
+ attr_reader :name
6
+ attr_reader :remote_siblings
7
+ attr_reader :supermodel
8
+ attr_reader :provided_models
9
+
10
+ def initialize(name, remote_siblings, supermodel, provided_models)
11
+ @name, @remote_siblings, @supermodel, @provided_models =
12
+ name, remote_siblings, supermodel, provided_models
13
+ end
14
+
15
+ def proxy(peer)
16
+ unmarshal_dependent_models(peer)
17
+ if local_m = peer.find_local_model(self)
18
+ # Ensures that the supermodel(s) are registered
19
+ return local_m
20
+ elsif !supermodel
21
+ raise NoLocalObject, "#{name}, at the root of a model hierarchy, was expected to be explicitely registered but is not"
22
+ else
23
+ create_new_proxy_model(peer)
24
+ end
25
+ end
26
+
27
+ def create_new_proxy_model(peer)
28
+ local_model = @unmarshalled_supermodel.
29
+ new_submodel(name: name || "#{@unmarshalled_supermodel.name}#")
30
+ peer.register_model(local_model, remote_siblings)
31
+ local_model
32
+ end
33
+
34
+ def unmarshal_dependent_models(peer)
35
+ # Ensure that the peer-local info of related models gets
36
+ # registered, no matter what.
37
+ if supermodel
38
+ @unmarshalled_supermodel = peer.local_model(supermodel)
39
+ end
40
+ @unmarshalled_provided_models = @provided_models.map { |m| peer.local_model(m) }
41
+ end
42
+
43
+ def update(peer, local_object, fresh_proxy: false)
44
+ @unmarshalled_provided_models ||= @provided_models.map { |m| peer.local_model(m) }
45
+ @unmarshalled_provided_models.each do |local_m|
46
+ if !(local_object <= local_m)
47
+ local_object.provides local_m
48
+ end
49
+ end
50
+ end
51
+
52
+ def self.dump_supermodel(peer, model)
53
+ s = model.supermodel
54
+ if s.kind_of?(ModelDumper)
55
+ peer.dump_model(s)
56
+ end
57
+ end
58
+
59
+ def self.dump_provided_models_of(peer, model)
60
+ provided_models_of(model).map do |m|
61
+ peer.dump_model(m)
62
+ end
63
+ end
64
+
65
+ def self.provided_models_of(model)
66
+ super_m = model.supermodel
67
+ provided_m = Array.new
68
+ model.ancestors.each do |m|
69
+ if m == super_m
70
+ break
71
+ elsif (m != model) && m.kind_of?(ModelDumper)
72
+ provided_m << m
73
+ end
74
+ end
75
+ provided_m
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+
@@ -0,0 +1,10 @@
1
+ module Roby
2
+ module DRoby
3
+ module V5
4
+ # Identification of a remote peer
5
+ class PeerID < DRobyID
6
+ end
7
+ end
8
+ end
9
+ end
10
+
@@ -0,0 +1,42 @@
1
+ module Roby
2
+ module DRoby
3
+ module V5
4
+ # Cross-instance identification of an object
5
+ class RemoteDRobyID
6
+ # The peer on which the object is known as {#droby_id}
7
+ #
8
+ # @return [PeerID]
9
+ attr_reader :peer_id
10
+
11
+ # The object ID
12
+ #
13
+ # @return [DRobyID]
14
+ attr_reader :droby_id
15
+
16
+ # The ID hash value
17
+ #
18
+ # The values are immutable, so the hash value is computed once
19
+ # and cached here
20
+ attr_reader :hash
21
+
22
+ def initialize(peer_id, droby_id)
23
+ @peer_id = peer_id
24
+ @droby_id = droby_id
25
+
26
+ @hash = [@peer_id, @droby_id].hash
27
+ end
28
+
29
+ def eql?(obj)
30
+ obj.kind_of?(RemoteDRobyID) &&
31
+ obj.peer_id == peer_id && obj.droby_id == droby_id
32
+ end
33
+ def ==(obj); eql?(obj) end
34
+
35
+ def to_s
36
+ "#<RemoteDRobyID #{peer_id}@#{droby_id}>"
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+
@@ -5,17 +5,19 @@ module Roby
5
5
  # functionalities related to propagation as well.
6
6
  class Event
7
7
  # The generator which emitted this event
8
- attr_reader :generator
8
+ attr_reader :generator
9
9
 
10
- @@creation_places = Hash.new
11
- def initialize(generator, propagation_id, context, time = Time.now)
12
- @generator, @propagation_id, @context, @time = generator, propagation_id, context.freeze, time
10
+ def initialize(generator, propagation_id, context, time = Time.now)
11
+ @generator, @propagation_id, @context, @time = generator, propagation_id, context.freeze, time
12
+ @sources = Set.new
13
+ end
13
14
 
14
- @@creation_places[object_id] = "#{generator.class}"
15
- end
15
+ def plan
16
+ generator.plan
17
+ end
16
18
 
17
- attr_accessor :propagation_id, :context, :time
18
- protected :propagation_id=, :context=, :time=
19
+ attr_accessor :propagation_id, :context, :time
20
+ protected :propagation_id=, :context=, :time=
19
21
 
20
22
  # The events whose emission directly triggered this event during the
21
23
  # propagation. The events in this set are subject to Ruby's own
@@ -23,992 +25,112 @@ def initialize(generator, propagation_id, context, time = Time.now)
23
25
  # collected (i.e. if all references to the associated task/event
24
26
  # generator are removed), it will be removed from this set as well.
25
27
  def sources
26
- result = []
28
+ result = Set.new
27
29
  @sources.delete_if do |ref|
28
30
  begin
29
- result << ref.get
31
+ result << ref.__getobj__
30
32
  false
31
- rescue Utilrb::WeakRef::RefError
33
+ rescue WeakRef::RefError
32
34
  true
33
35
  end
34
36
  end
35
37
  result
36
38
  end
37
39
 
38
- # Sets the sources. See #sources
39
- def sources=(sources) # :nodoc:
40
- @sources = ValueSet.new
41
- for s in sources
42
- @sources << Utilrb::WeakRef.new(s)
40
+ # Recursively computes the source event that led to the emission of
41
+ # +self+
42
+ def all_sources
43
+ result = Set.new
44
+ sources.each do |ev|
45
+ result << ev
46
+ result.merge(ev.all_sources)
43
47
  end
48
+ result
44
49
  end
45
50
 
46
- # To be used in the event generators ::new methods, when we need to reemit
47
- # an event while changing its
48
- def reemit(new_id, new_context = nil)
49
- if propagation_id != new_id || (new_context && new_context != context)
50
- new_event = self.dup
51
- new_event.propagation_id = new_id
52
- new_event.context = new_context
53
- new_event.time = Time.now
54
- new_event
55
- else
56
- self
57
- end
58
- end
59
-
60
- def name; model.name end
61
- def model; self.class end
62
- def inspect # :nodoc:
63
- "#<#{model.to_s}:0x#{address.to_s(16)} generator=#{generator} model=#{model}"
51
+ # Call to protect this event's source from Ruby's garbage collection.
52
+ # Call this if you want to store the propagation history for this event
53
+ def protect_sources
54
+ @protected_sources = sources
64
55
  end
65
56
 
66
- # Returns an event generator which will be emitted once +time+ seconds
67
- # after this event has been emitted.
68
- def after(time)
69
- State.at :t => (self.time + time)
57
+ # Call to recursively protect this event's sources from Ruby's garbage
58
+ # collection. Call this if you want to store the propagation history for
59
+ # this event
60
+ def protect_all_sources
61
+ @protected_all_sources = all_sources
70
62
  end
71
63
 
72
- def to_s # :nodoc:
73
- "[#{time.to_hms} @#{propagation_id}] #{self.class.to_s}: #{context}"
74
- end
64
+ # Sets the sources. See #sources
65
+ def sources=(new_sources) # :nodoc:
66
+ @sources = Set.new
67
+ add_sources(new_sources)
68
+ end
75
69
 
76
- def pretty_print(pp) # :nodoc:
77
- pp.text "[#{time.to_hms} @#{propagation_id}] #{self.class}"
78
- if context
79
- pp.breakable
80
- pp.nest(2) do
81
- pp.text " "
82
- pp.seplist(context) { |v| v.pretty_print(pp) }
83
- end
70
+ def add_sources(new_sources)
71
+ for new_s in new_sources
72
+ @sources << WeakRef.new(new_s)
84
73
  end
85
74
  end
86
- end
87
-
88
- # EventGenerator objects are the objects which manage the event generation
89
- # process (propagation, event creation, ...). They can be combined
90
- # logically using & and |.
91
- #
92
- # === Standard relations
93
- # - signals: calls the *command* of an event when this generator emits
94
- # - forwardings: *emits* another event when this generator emits
95
- #
96
- # === Hooks
97
- # The following hooks are defined:
98
- # * #postponed
99
- # * #calling
100
- # * #called
101
- # * #fired
102
- # * #signalling
103
- # * #forwarding
104
- #
105
- class EventGenerator < PlanObject
106
- # Creates a new Event generator which is emitted as soon as one of this
107
- # object and +generator+ is emitted
108
- def |(generator)
109
- OrGenerator.new << self << generator
110
- end
111
-
112
- # Creates a AndGenerator object which is emitted when both this object
113
- # and +generator+ are emitted
114
- def &(generator)
115
- AndGenerator.new << self << generator
116
- end
117
-
118
- attr_enumerable(:handler, :handlers) { Array.new }
119
- attr_enumerable(:once_handler, :once_handlers) { Array.new }
120
-
121
- def initialize_copy(old) # :nodoc:
122
- super
123
-
124
- @history = old.history.dup
125
- end
126
-
127
- def model; self.class end
128
- # The model name
129
- def name; model.name end
130
- # The count of command calls that have not a corresponding emission
131
- attr_reader :pending
132
- # True if this event has been called but is not emitted yet
133
- def pending?; pending end
134
-
135
- # call-seq:
136
- # EventGenerator.new
137
- # EventGenerator.new(false)
138
- # EventGenerator.new(true)
139
- # EventGenerator.new { |event| ... }
140
- #
141
- # Create a new event generator. If a block is given, the event is
142
- # controlable and the block is its command. If a +true+ argument is
143
- # given, the event is controlable and is 'pass-through': it is emitted
144
- # as soon as its command is called. If no argument is given (or a
145
- # +false+ argument), then it is not controlable
146
- def initialize(command_object = nil, &command_block)
147
- @preconditions = []
148
- @handlers = []
149
- @pending = false
150
- @unreachable = false
151
- @unreachable_handlers = []
152
-
153
- if command_object || command_block
154
- self.command = if command_object.respond_to?(:call)
155
- command_object
156
- elsif command_block
157
- command_block
158
- else
159
- method(:default_command)
160
- end
161
- end
162
- super() if defined? super
163
-
164
- end
165
-
166
- def default_command(context)
167
- emit(*context)
168
- end
169
-
170
- # The current command block
171
- attr_accessor :command
172
-
173
- # True if this event is controlable
174
- def controlable?; !!@command end
175
-
176
- # Checks that the event can be called. Raises various exception
177
- # when it is not the case.
178
- def check_call_validity
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"
185
- elsif !controlable?
186
- raise EventNotControlable.new(self), "#call called on a non-controlable event"
187
- elsif !engine.inside_control?
188
- raise ThreadMismatch, "#call called while not in control thread"
189
- end
190
- end
191
-
192
- # Checks that the event can be emitted. Raises various exception
193
- # when it is not the case.
194
- def check_emission_validity
195
- if !executable?
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?
200
- raise ThreadMismatch, "#emit called while not in control thread"
201
- end
202
- end
203
-
204
- # Returns true if the command has been called and false otherwise
205
- # The command won't be called if #postpone() is called within the
206
- # #calling hook, in which case the method returns false.
207
- #
208
- # This is used by propagation code, and should never be called directly
209
- def call_without_propagation(context)
210
- check_call_validity
211
-
212
- if !controlable?
213
- raise EventNotControlable.new(self), "#call called on a non-controlable event"
214
- end
215
-
216
- postponed = catch :postponed do
217
- calling(context)
218
- @pending = true
219
-
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
225
- command[context]
226
- end
227
-
228
- false
229
- end
230
-
231
- if postponed
232
- @pending = false
233
- postponed(context, *postponed)
234
- false
235
- else
236
- called(context)
237
- true
238
- end
239
-
240
- rescue Exception
241
- @pending = false
242
- raise
243
- end
244
75
 
245
- # Call the command associated with self. Note that an event might be
246
- # non-controlable and respond to the :call message. Controlability must
247
- # be checked using #controlable?
248
- def call(*context)
249
- check_call_validity
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"
76
+ def root_sources
77
+ all = all_sources
78
+ all.find_all do |event|
79
+ all.none? { |ev| ev.generator.child_object?(event.generator, Roby::EventStructure::Forwarding) }
257
80
  end
258
-
259
- context.compact!
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)
267
- end
268
- if errors.size == 1
269
- e = errors.first.exception
270
- raise e.dup, e.message, Roby.filter_backtrace(e.backtrace)
271
- elsif !errors.empty?
272
- for e in errors
273
- pp e.exception
274
- end
275
- raise "multiple exceptions"
276
- end
277
- end
278
- end
279
- end
280
-
281
- # call-seq:
282
- # on { |event| ... }
283
- #
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.
287
- def on(signal = nil, time = nil, &handler)
288
- if signal
289
- Roby.warn_deprecated "EventGenerator#on only accepts event handlers now. Use #signals to establish signalling"
290
- self.signals(signal, time)
291
- end
292
-
293
- if handler
294
- check_arity(handler, 1)
295
- self.handlers << handler
296
- end
297
-
298
- self
299
- end
300
-
301
- # Adds a signal from this event to +generator+. +generator+ must be
302
- # controlable.
303
- #
304
- # If +time+ is given it is either a :delay => time association, or a
305
- # :at => time association. In the first case, +time+ is a floating-point
306
- # delay in seconds and in the second case it is a Time object which is
307
- # the absolute point in time at which this propagation must happen.
308
- def signals(generator, timespec = nil)
309
- if !generator.controlable?
310
- raise EventNotControlable.new(self), "trying to establish a signal from #{self} to #{generator} which is not controllable"
311
- end
312
- timespec = ExecutionEngine.validate_timespec(timespec)
313
-
314
- add_signal generator, timespec
315
- self
316
81
  end
317
82
 
318
- def signal(generator, timespec = nil)
319
- Roby.warn_deprecated "EventGenerator#signal has been renamed into EventGenerator#signals"
320
- signals(generator, timespec)
321
- end
322
-
323
- # A set of blocks called when this event cannot be emitted again
324
- attr_reader :unreachable_handlers
325
-
326
- # Calls +block+ if it is impossible that this event is ever emitted
327
- def if_unreachable(cancel_at_emission = false, &block)
328
- unreachable_handlers << [cancel_at_emission, block]
329
- block.object_id
330
- end
331
-
332
- # Returns an event which will be emitted when this event becones
333
- # unreachable
334
- def when_unreachable
335
- # NOTE: the unreachable event is not directly tied to this one from
336
- # a GC point of view (being able to do this would be useful, but
337
- # anyway). So, it is possible that it is GCed because the event
338
- # user did not take care to use it.
339
- if !@unreachable_event || !@unreachable_event.plan
340
- result = EventGenerator.new(true)
341
- if_unreachable(false) do
342
- if result.plan
343
- result.emit
344
- end
345
- end
346
- add_causal_link result
347
- @unreachable_event = result
83
+ # To be used in the event generators ::new methods, when we need to reemit
84
+ # an event while changing its
85
+ def reemit(new_id, new_context = nil)
86
+ if propagation_id != new_id || (new_context && new_context != context)
87
+ new_event = self.dup
88
+ new_event.propagation_id = new_id
89
+ new_event.context = new_context
90
+ new_event.time = Time.now
91
+ new_event
92
+ else
93
+ self
348
94
  end
349
- @unreachable_event
350
95
  end
351
96
 
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
-
357
- # Emit +generator+ when +self+ is fired, without calling the command of
358
- # +generator+, if any.
359
- #
360
- # If +timespec+ is given it is either a :delay => time association, or a
361
- # :at => time association. In the first case, +time+ is a floating-point
362
- # delay in seconds and in the second case it is a Time object which is
363
- # the absolute point in time at which this propagation must happen.
364
- def forward_to(generator, timespec = nil)
365
- timespec = ExecutionEngine.validate_timespec(timespec)
366
- add_forwarding generator, timespec
367
- self
97
+ def name; model.name end
98
+ def model; self.class end
99
+ def inspect # :nodoc:
100
+ "#<#{model.to_s}:0x#{address.to_s(16)} generator=#{generator} model=#{model}"
368
101
  end
369
102
 
370
- # Returns an event which is emitted +seconds+ seconds after this one
371
- def delay(seconds)
372
- if seconds == 0 then self
373
- else
374
- ev = EventGenerator.new
375
- forward_to(ev, :delay => seconds)
376
- ev
377
- end
378
- end
379
-
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
385
- end
386
- self
103
+ # Returns an event generator which will be emitted once +time+ seconds
104
+ # after this event has been emitted.
105
+ def after(time)
106
+ State.at t: (self.time + time)
387
107
  end
388
108
 
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
401
- end
402
-
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)
109
+ def to_s # :nodoc:
110
+ "[#{Roby.format_time(time)} @#{propagation_id}] #{self.class.to_s}: #{context}"
406
111
  end
407
112
 
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|
412
- remove_forwarding ev
413
- end
414
- self
415
- end
416
-
417
- def to_event; self end
418
-
419
- # Returns the set of events directly related to this one
420
- def related_events(result = nil); related_objects(nil, result) end
421
- # Returns the set of tasks directly related to this event
422
- def related_tasks(result = nil)
423
- result ||= ValueSet.new
424
- for ev in related_events
425
- if ev.respond_to?(:task)
426
- result << ev.task
427
- end
428
- end
429
- result
430
- end
431
-
432
- # Create a new event object for +context+
433
- def new(context); Event.new(self, plan.engine.propagation_id, context, Time.now) end
434
-
435
- # Adds a propagation originating from this event to event propagation
436
- def add_propagation(only_forward, event, signalled, context, timespec) # :nodoc:
437
- if self == signalled
438
- raise PropagationError, "#{self} is trying to signal itself"
439
- elsif !only_forward && !signalled.controlable?
440
- raise PropagationError, "trying to signal #{signalled} from #{self}"
441
- end
442
-
443
- plan.engine.add_event_propagation(only_forward, [event], signalled, context, timespec)
444
- end
445
- private :add_propagation
446
-
447
- # Do fire this event. It gathers the list of signals that are to
448
- # be propagated in the next step and calls fired()
449
- #
450
- # This method is always called in a propagation context
451
- def fire(event)
452
- plan.engine.propagation_context([event]) do |result|
453
- each_signal do |signalled|
454
- add_propagation(false, event, signalled, event.context, self[signalled, EventStructure::Signal])
455
- end
456
- each_forwarding do |signalled|
457
- add_propagation(true, event, signalled, event.context, self[signalled, EventStructure::Forwarding])
458
- end
459
-
460
- @happened = true
461
- fired(event)
462
-
463
- call_handlers(event)
464
- end
465
- end
466
-
467
- private :fire
468
-
469
- # Call the event handlers defined for this event generator
470
- def call_handlers(event)
471
- # Since we are in a gathering context, call
472
- # to other objects are not done, but gathered in the
473
- # :propagation TLS
474
- each_handler do |h|
475
- begin
476
- h.call(event)
477
- rescue Exception => e
478
- plan.engine.add_error( EventHandlerError.new(e, event) )
479
- end
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
489
- end
490
-
491
- # Raises an exception object when an event whose command has been
492
- # called won't be emitted (ever)
493
- def emit_failed(*what)
494
- what, message = *what
495
- what ||= EmissionFailed
496
-
497
- if !message && !(what.kind_of?(Class) || what.kind_of?(Exception))
498
- message = what.to_str
499
- what = EmissionFailed
500
- end
501
-
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}"
113
+ def pretty_print(pp, with_context = true) # :nodoc:
114
+ pp.text "[#{Roby.format_time(time)} @#{propagation_id}] #{self.class}"
115
+ if with_context && context
116
+ pp.breakable
117
+ pp.text "with context"
118
+ pp.nest(2) do
119
+ pp.text " "
120
+ pp.seplist(context) do |v|
121
+ v.pretty_print(pp)
122
+ end
506
123
  end
507
-
508
- error = if Class === what then what.new(nil, self)
509
- else what
510
- end
511
-
512
- new_error = error.exception failure_message
513
- new_error.set_backtrace error.backtrace
514
- error = new_error
515
-
516
- if !error.kind_of?(LocalizedError)
517
- error = EmissionFailed.new(error, self)
518
- end
519
-
520
- plan.engine.add_error(error)
521
- ensure
522
- @pending = false
523
- end
524
-
525
- # Emits the event regardless of wether we are in a propagation context
526
- # or not. Returns true to match the behavior of #call_without_propagation
527
- #
528
- # This is used by event propagation. Do not call directly: use #call instead
529
- def emit_without_propagation(context)
530
- check_emission_validity
531
-
532
- if !executable?
533
- raise EventNotExecutable.new(self), "#emit called on #{self} which is not executable"
534
- end
535
-
536
- emitting(context)
537
-
538
- # Create the event object
539
- event = new(context)
540
- unless event.respond_to?(:context)
541
- raise TypeError, "#{event} is not a valid event object in #{self}"
542
- end
543
- event.sources = plan.engine.propagation_source_events
544
- fire(event)
545
-
546
- true
547
-
548
- ensure
549
- @pending = false
550
- end
551
-
552
- # Emit the event with +context+ as the event context
553
- def emit(*context)
554
- check_emission_validity
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
-
564
- context.compact!
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)
572
- end
573
- if errors.size == 1
574
- e = errors.first.exception
575
- raise e.dup, e.message, Roby.filter_backtrace(e.backtrace)
576
- elsif !errors.empty?
577
- for e in errors
578
- pp e.exception
579
- end
580
- raise "multiple exceptions"
581
- end
582
- end
583
- end
584
- end
585
-
586
- # Deprecated. Instead of using
587
- # dest.emit_on(source)
588
- # now use
589
- # source.forward_to(dest)
590
- def emit_on(generator, timespec = nil)
591
- Roby.warn_deprecated "a.emit_on(b) has been replaced by b.forward_to(a)"
592
- generator.forward(self, timespec)
593
- self
594
- end
595
-
596
- # Sets up +ev+ and +self+ to represent that the command of +self+ is to
597
- # be achieved by the emission of +ev+. It is to be used in a command
598
- # handler:
599
- #
600
- # event :start do |context|
601
- # init = <create an initialization event>
602
- # event(:start).achieve_with(init)
603
- # end
604
- #
605
- # If +ev+ becomes unreachable, an EmissionFailed exception will be
606
- # raised. If a block is given, it is supposed to return the context of
607
- # the event emitted by +self+, given the context of the event emitted
608
- # by +ev+.
609
- #
610
- # From an event propagation point of view, it looks like:
611
- # TODO: add a figure
612
- def achieve_with(ev)
613
- stack = caller(1)
614
- if block_given?
615
- ev.add_causal_link self
616
- ev.once do |context|
617
- self.emit(yield(context))
618
- end
619
- else
620
- ev.forward_to_once self
621
- end
622
-
623
- ev.if_unreachable(true) do |reason|
624
- emit_failed(UnreachableEvent.new(self, reason))
625
- end
626
- end
627
- # For backwards compatibility. Use #achieve_with.
628
- def realize_with(task); achieve_with(task) end
629
-
630
- # A [time, event] array of past event emitted by this object
631
- attribute(:history) { Array.new }
632
- # True if this event has been emitted once.
633
- attr_predicate :happened
634
- # Last event to have been emitted by this generator
635
- def last; history.last end
636
-
637
- # Defines a precondition handler for this event. Precondition handlers
638
- # are blocks which are called just before the event command is called.
639
- # If the handler returns false, the calling is aborted by a
640
- # PreconditionFailed exception
641
- def precondition(reason = nil, &block)
642
- @preconditions << [reason, block]
643
- end
644
-
645
- # Yields all precondition handlers defined for this generator
646
- def each_precondition # :yield:reason, block
647
- @preconditions.each { |o| yield(o) }
648
- end
649
-
650
- # Call #postpone in #calling to announce that the event should not be
651
- # called now, but should be called back when +generator+ is emitted
652
- #
653
- # A reason string can be provided for debugging purposes
654
- def postpone(generator, reason = nil)
655
- generator.signals self
656
- yield if block_given?
657
- throw :postponed, [generator, reason]
658
- end
659
-
660
- # Hook called when the event has been postponed. See #postpone
661
- def postponed(context, generator, reason); super if defined? super end
662
-
663
- # Call this method in the #calling hook to cancel calling the event
664
- # command. This raises an EventCanceled exception with +reason+ for
665
- # message
666
- def cancel(reason = nil)
667
- raise EventCanceled.new(self), (reason || "event canceled")
668
- end
669
-
670
- # Hook called when this event generator is called (i.e. the associated
671
- # command is), before the command is actually called. Think of it as a
672
- # pre-call hook.
673
- #
674
- # The #postpone method can be called in this hook
675
- def calling(context)
676
- super if defined? super
677
- each_precondition do |reason, block|
678
- result = begin
679
- block.call(self, context)
680
- rescue EventPreconditionFailed => e
681
- e.generator = self
682
- raise
683
- end
684
-
685
- if !result
686
- raise EventPreconditionFailed.new(self), "precondition #{reason} failed"
687
- end
688
- end
689
- end
690
-
691
- # Hook called just after the event command has been called
692
- def called(context); super if defined? super end
693
-
694
- # Hook called when this generator has been fired. +event+ is the Event object
695
- # which has been created.
696
- def fired(event)
697
- unreachable_handlers.delete_if { |cancel, _| cancel }
698
-
699
- history << event
700
- if EventGenerator.event_gathering.has_key?(event.generator)
701
- for c in EventGenerator.event_gathering[event.generator]
702
- c << event
703
- end
704
- end
705
-
706
- super if defined? super
707
- end
708
-
709
- # Hook called just before the +to+ generator is signalled by this
710
- # generator. +event+ is the Event object which has been generated by
711
- # this model
712
- def signalling(event, to); super if defined? super end
713
-
714
- # Hook called just before the propagation forwards +self+ to +to+.
715
- # +event+ is the Event object which has been generated by this model
716
- def forwarding(event, to); super if defined? super end
717
-
718
- # Hook called when this event will be emitted
719
- def emitting(context); super if defined? super end
720
-
721
- # call-seq:
722
- # filter(new_context) => filtering_event
723
- # filter { |context| ... } => filtering_event
724
- #
725
- # Returns an event generator which forwards the events fired by this
726
- # one, but by changing the context. In the first form, the new context
727
- # is set to +new_context+. In the second form, to the value returned
728
- # by the given block
729
- def filter(*new_context, &block)
730
- filter = FilterGenerator.new(new_context, &block)
731
- self.signals(filter)
732
- filter
733
- end
734
-
735
- # Returns a new event generator which emits until the +limit+ event is
736
- # sent
737
- #
738
- # source, ev, limit = (1..3).map { EventGenerator.new(true) }
739
- # ev.until(limit).on { STDERR.puts "FIRED !!!" }
740
- # source.signals ev
741
- #
742
- # Will do
743
- #
744
- # source.call # => FIRED !!!
745
- # limit.emit
746
- # source.call # =>
747
- #
748
- # See also UntilGenerator
749
- def until(limit); UntilGenerator.new(self, limit) end
750
-
751
- # Checks that ownership allows to add the self => child relation
752
- def add_child_object(child, type, info) # :nodoc:
753
- unless child.read_write?
754
- raise OwnershipError, "cannot add an event relation on a child we don't own. #{child} is owned by #{child.owners.to_a} (plan is owned by #{plan.owners.to_a if plan})"
755
- end
756
-
757
- super
758
- end
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
124
  end
771
125
  end
772
126
 
773
- @@event_gathering = Hash.new { |h, k| h[k] = ValueSet.new }
774
- # If a generator in +events+ fires, add the fired event in +collection+
775
- def self.gather_events(collection, events)
776
- for ev in events
777
- event_gathering[ev] << collection
778
- end
779
- end
780
- # Remove the notifications that have been registered for +collection+
781
- def self.remove_event_gathering(collection)
782
- @@event_gathering.delete_if do |_, collections|
783
- collections.delete(collection)
784
- collections.empty?
785
- end
786
- end
787
- # An array of [collection, events] elements, collection being the
788
- # object in which we must add the fired events, and events the set of
789
- # event generators +collection+ is listening for.
790
- def self.event_gathering; @@event_gathering end
791
-
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
798
-
799
- # Called internally when the event becomes unreachable
800
- def unreachable!(reason = nil, plan = self.plan)
801
- return if @unreachable
802
- @unreachable = true
803
- @unreachability_reason = reason
804
-
805
- EventGenerator.event_gathering.delete(self)
806
-
807
- unreachable_handlers.each do |_, block|
808
- begin
809
- block.call(reason)
810
- rescue LocalizedError => e
811
- plan.engine.add_error(e)
812
- rescue Exception => e
813
- plan.engine.add_error(EventHandlerError.new(e, self))
814
- end
815
- end
816
- unreachable_handlers.clear
817
- end
818
-
819
- def pretty_print(pp) # :nodoc:
820
- pp.text to_s
821
- pp.group(2, ' {', '}') do
822
- pp.breakable
823
- pp.text "owners: "
824
- pp.seplist(owners) { |r| pp.text r.to_s }
825
-
826
- pp.breakable
827
- pp.text "relations: "
828
- pp.seplist(relations) { |r| pp.text r.name }
829
- end
830
- end
831
- end
832
-
833
-
834
- # This generator reemits an event after having changed its context. See
835
- # EventGenerator#filter for a more complete explanation
836
- class FilterGenerator < EventGenerator
837
- def initialize(user_context, &block)
838
- if block && !user_context.empty?
839
- raise ArgumentError, "you must set either the filter or the value, not both"
840
- end
841
-
842
- if block
843
- super() do |context|
844
- context = context.map do |val|
845
- block.call(val)
846
- end
847
- emit(*context)
848
- end
849
- else
850
- super() do
851
- emit(*user_context)
852
- end
853
- end
854
- end
855
- end
856
-
857
- # Event generator which fires when all its source events have fired
858
- # See EventGenerator#& for a more complete description
859
- class AndGenerator < EventGenerator
860
- def initialize
861
- super do |context|
862
- emit_if_achieved(context)
863
- end
864
-
865
- # This hash is a event_generator => event mapping of the last
866
- # events of each event generator. We compare the event stored in
867
- # this hash with the last events of each source to know if the
868
- # source fired since it has been added to this AndGenerator
869
- @events = Hash.new
870
-
871
- # This flag is true unless we are not waiting for the emission
872
- # anymore.
873
- @active = true
874
- end
875
-
876
- # Resets the waiting. If the event has already been emitted, it re-arms
877
- # it.
878
- def reset
879
- @active = true
880
- each_parent_object(EventStructure::Signal) do |source|
881
- @events[source] = source.last
882
- if source.respond_to?(:reset)
883
- source.reset
884
- end
885
- end
886
- end
887
-
888
- def emit_if_achieved(context) # :nodoc:
889
- return unless @active
890
- each_parent_object(EventStructure::Signal) do |source|
891
- return if @events[source] == source.last
892
- end
893
- @active = false
894
- emit(nil)
895
- end
896
-
897
- def empty?; events.empty? end
898
-
899
- # Adds a new source to +events+ when a source event is added
900
- def added_parent_object(parent, relations, info) # :nodoc:
901
- super if defined? super
902
- return unless relations.include?(EventStructure::Signal)
903
- @events[parent] = parent.last
904
-
905
- # If the parent is unreachable, check that it has neither been
906
- # removed, nor it has been emitted
907
- parent.if_unreachable(true) do |reason|
908
- if @events[parent] == parent.last
909
- unreachable!(reason || parent)
910
- end
911
- end
912
- end
913
-
914
- # Removes a source from +events+ when the source is removed
915
- def removed_parent_object(parent, relations) # :nodoc:
916
- super if defined? super
917
- return unless relations.include?(EventStructure::Signal)
918
- @events.delete(parent)
919
- end
920
-
921
- # The set of source events
922
- def events; parent_objects(EventStructure::Signal) end
923
- # The set of events which we are waiting for
924
- def waiting; parent_objects(EventStructure::Signal).find_all { |ev| @events[ev] == ev.last } end
925
-
926
- # Add a new source to this generator
927
- def << (generator)
928
- generator.add_signal self
929
- self
930
- end
931
- end
932
-
933
- # Event generator which fires when the first of its source events fires.
934
- # All event generators which signal this one are considered as sources.
935
- #
936
- # See also EventGenerator#| and #<<
937
- class OrGenerator < EventGenerator
938
- # Creates a new OrGenerator without any sources.
939
- def initialize
940
- super do |context|
941
- emit_if_first(context)
942
- end
943
- @active = true
944
- end
945
-
946
- # True if there is no source event for this combinator.
947
- def empty?; parent_objects(EventStructure::Signal).empty? end
948
-
949
- # Reset its state, so as to behave as if no source has ever
950
- # been emitted.
951
- def reset
952
- @active = true
953
- each_parent_object(EventStructure::Signal) do |source|
954
- if source.respond_to?(:reset)
955
- source.reset
956
- end
957
- end
958
- end
959
-
960
- def emit_if_first(context) # :nodoc:
961
- return unless @active
962
- @active = false
963
- emit(context)
964
- end
965
-
966
- def added_parent_object(parent, relations, info) # :nodoc:
967
- super if defined? super
968
- return unless relations.include?(EventStructure::Signal)
969
-
970
- parent.if_unreachable(true) do |reason|
971
- if !happened? && parent_objects(EventStructure::Signal).all? { |ev| ev.unreachable? }
972
- unreachable!(reason || parent)
973
- end
974
- end
975
- end
976
-
977
- # Adds +generator+ to the sources of this event
978
- def << (generator)
979
- generator.add_signal self
980
- self
981
- end
982
- end
983
-
984
- # This event generator combines a source and a limit in a temporal pattern.
985
- # The generator acts as a pass-through for the source, until the limit is
986
- # itself emitted. It means that:
987
- #
988
- # * before the limit is emitted, the generator will emit each time its
989
- # source emits
990
- # * since the point where the limit is emitted, the generator
991
- # does not emit anymore
992
- #
993
- # See also EventGenerator#until
994
- class UntilGenerator < Roby::EventGenerator
995
- # Creates a until generator for the given source and limit event
996
- # generators
997
- def initialize(source = nil, limit = nil)
998
- super() do |context|
999
- plan.remove_object(self) if plan
1000
- clear_relations
1001
- end
1002
-
1003
- if source && limit
1004
- source.forward_to(self)
1005
- limit.signals(self)
1006
- end
1007
- end
1008
- end
127
+ def to_execution_exception
128
+ generator.to_execution_exception
129
+ end
1009
130
 
1010
- unless defined? EventStructure
1011
- EventStructure = RelationSpace(EventGenerator)
131
+ def to_execution_exception_matcher
132
+ generator.to_execution_exception_matcher
133
+ end
1012
134
  end
1013
135
  end
1014
136