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.
- checksums.yaml +7 -0
- data/.deep-cover.rb +3 -0
- data/.gitattributes +1 -0
- data/.gitignore +24 -0
- data/.simplecov +10 -0
- data/.travis.yml +17 -0
- data/.yardopts +4 -0
- data/Gemfile +15 -0
- data/README.md +11 -0
- data/Rakefile +47 -177
- data/benchmark/{alloc_misc.rb → attic/alloc_misc.rb} +2 -2
- data/benchmark/{discovery_latency.rb → attic/discovery_latency.rb} +19 -19
- data/benchmark/{garbage_collection.rb → attic/garbage_collection.rb} +9 -9
- data/benchmark/{genom.rb → attic/genom.rb} +0 -0
- data/benchmark/attic/transactions.rb +62 -0
- data/benchmark/plan_basic_operations.rb +28 -0
- data/benchmark/relations/graph.rb +63 -0
- data/benchmark/ruby/identity.rb +18 -0
- data/benchmark/ruby/set_intersect_vs_hash_merge.rb +39 -0
- data/benchmark/ruby/yield_vs_block.rb +35 -0
- data/benchmark/run +5 -0
- data/benchmark/synthetic_plan_modifications_with_transactions.rb +79 -0
- data/benchmark/transactions.rb +99 -51
- data/bin/roby +38 -197
- data/bin/roby-display +14 -0
- data/bin/roby-log +3 -176
- data/doc/guide/{src → attic}/abstraction/achieve_with.page +1 -1
- data/doc/guide/{src → attic}/abstraction/forwarding.page +1 -1
- data/doc/guide/{src → attic}/abstraction/hierarchy.page +1 -1
- data/doc/guide/{src → attic}/abstraction/index.page +1 -1
- data/doc/guide/{src → attic}/abstraction/task_models.page +1 -1
- data/doc/guide/{overview.rdoc → attic/cycle/api_overview.rdoc} +6 -1
- data/doc/guide/{src → attic}/cycle/cycle-overview.png +0 -0
- data/doc/guide/{src → attic}/cycle/cycle-overview.svg +0 -0
- data/doc/guide/attic/cycle/error_handling.page +98 -0
- data/doc/guide/{src → attic}/cycle/error_instantaneous_repair.png +0 -0
- data/doc/guide/{src → attic}/cycle/error_instantaneous_repair.svg +0 -0
- data/doc/guide/{src/cycle/error_handling.page → attic/cycle/error_sources.page} +46 -89
- data/doc/guide/{src → attic}/cycle/garbage_collection.page +1 -1
- data/doc/guide/{src → attic}/cycle/index.page +1 -1
- data/doc/guide/{src → attic}/cycle/propagation.page +11 -1
- data/doc/guide/{src → attic}/cycle/propagation_diamond.png +0 -0
- data/doc/guide/{src → attic}/cycle/propagation_diamond.svg +0 -0
- data/doc/guide/attic/plans/building_plans.page +89 -0
- data/doc/guide/attic/plans/code.page +192 -0
- data/doc/guide/{src/basics → attic/plans}/events.page +3 -4
- data/doc/guide/attic/plans/index.page +7 -0
- data/doc/guide/{plan_modifications.rdoc → attic/plans/plan_modifications.rdoc} +5 -3
- data/doc/guide/{src/basics → attic/plans}/plan_objects.page +2 -1
- data/doc/guide/attic/plans/querying_plans.page +5 -0
- data/doc/guide/{src/basics → attic/plans}/tasks.page +20 -20
- data/doc/guide/config.yaml +7 -4
- data/doc/guide/ext/extended_menu.rb +29 -0
- data/doc/guide/ext/init.rb +6 -0
- data/doc/guide/ext/rdoc_links.rb +7 -6
- data/doc/guide/src/advanced_concepts/history.page +5 -0
- data/doc/guide/src/advanced_concepts/index.page +11 -0
- data/doc/guide/src/advanced_concepts/recognizing_patterns.page +83 -0
- data/doc/guide/src/advanced_concepts/scheduling.page +87 -0
- data/doc/guide/src/advanced_concepts/transactions.page +5 -0
- data/doc/guide/src/advanced_concepts/unreachability.page +42 -0
- data/doc/guide/src/base.template +96 -0
- data/doc/guide/src/basics_shell_header.txt +5 -7
- data/doc/guide/src/building/action_coordination.page +96 -0
- data/doc/guide/src/building/actions.page +124 -0
- data/doc/guide/src/building/file_layout.page +71 -0
- data/doc/guide/src/building/index.page +50 -0
- data/doc/guide/src/building/patterns.page +86 -0
- data/doc/guide/src/building/patterns_forwarding.png +0 -0
- data/doc/guide/src/building/patterns_forwarding.svg +277 -0
- data/doc/guide/src/building/runtime.page +95 -0
- data/doc/guide/src/building/task_models.page +94 -0
- data/doc/guide/src/building/tasks.page +284 -0
- data/doc/guide/src/concepts/error_handling.page +100 -0
- data/doc/guide/src/concepts/exception_propagation.png +0 -0
- data/doc/guide/src/concepts/exception_propagation.svg +445 -0
- data/doc/guide/src/concepts/execution.page +85 -0
- data/doc/guide/src/concepts/execution.png +0 -0
- data/doc/guide/src/concepts/execution.svg +573 -0
- data/doc/guide/src/concepts/execution_cycle.png +0 -0
- data/doc/guide/src/concepts/garbage_collection.page +57 -0
- data/doc/guide/src/concepts/index.page +27 -0
- data/doc/guide/src/concepts/plans.page +101 -0
- data/doc/guide/src/concepts/policy.page +31 -0
- data/doc/guide/src/concepts/reactor.page +61 -0
- data/doc/guide/src/concepts/simple_plan_example.png +0 -0
- data/doc/guide/src/concepts/simple_plan_example.svg +376 -0
- data/doc/guide/src/default.template +9 -74
- data/doc/guide/src/event_relations/forward.page +71 -0
- data/doc/guide/src/event_relations/index.page +12 -0
- data/doc/guide/src/event_relations/scheduling_constraints.page +43 -0
- data/doc/guide/src/event_relations/signal.page +55 -0
- data/doc/guide/src/event_relations/temporal_constraints.page +77 -0
- data/doc/guide/src/htmldoc.metainfo +21 -8
- data/doc/guide/src/index.page +8 -3
- data/doc/guide/src/{introduction/install.page → installation/index.page} +37 -25
- data/doc/guide/src/installation/publications.page +14 -0
- data/doc/guide/src/{introduction → installation}/videos.page +14 -7
- data/doc/guide/src/interacting/index.page +16 -0
- data/doc/guide/src/interacting/run.page +33 -0
- data/doc/guide/src/interacting/shell.page +95 -0
- data/doc/guide/src/plugins/creating_plugins.page +72 -0
- data/doc/guide/src/plugins/index.page +27 -5
- data/doc/guide/src/plugins/{fault_tolerance.page → standard_plugins/fault_tolerance.page} +2 -2
- data/doc/guide/src/plugins/standard_plugins/index.page +11 -0
- data/doc/guide/src/plugins/{subsystems.page → standard_plugins/subsystems.page} +2 -2
- data/doc/guide/src/style_screen.css +687 -0
- data/doc/guide/src/task_relations/dependency.page +107 -0
- data/doc/guide/src/task_relations/executed_by.page +77 -0
- data/doc/guide/src/task_relations/index.page +12 -0
- data/doc/guide/src/task_relations/new_relations.page +119 -0
- data/doc/guide/src/task_relations/planned_by.page +46 -0
- data/doc/guide/src/tutorial/app.page +117 -0
- data/doc/guide/src/{basics → tutorial}/code_examples.page +6 -5
- data/doc/guide/src/{basics → tutorial}/dry.page +15 -15
- data/doc/guide/src/{basics → tutorial}/errors.page +43 -68
- data/doc/guide/src/tutorial/events.page +195 -0
- data/doc/guide/src/{basics → tutorial}/hierarchy.page +53 -52
- data/doc/guide/src/tutorial/index.page +13 -0
- data/doc/guide/src/tutorial/log_replay/goForward_1.png +0 -0
- data/doc/guide/src/tutorial/log_replay/goForward_2.png +0 -0
- data/doc/guide/src/tutorial/log_replay/goForward_3.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/goForward_4.png +0 -0
- data/doc/guide/src/tutorial/log_replay/goForward_5.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_1.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_2.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_3.png +0 -0
- data/doc/guide/src/tutorial/log_replay/moveto_code_error.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_1.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_2.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_3.png +0 -0
- data/doc/guide/src/tutorial/log_replay/plan_repair_4.png +0 -0
- data/doc/guide/src/tutorial/log_replay/roby_log_main_window.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/roby_log_relation_window.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/roby_replay_event_representation.png +0 -0
- data/doc/guide/src/tutorial/relations_display.page +153 -0
- data/doc/guide/src/{basics → tutorial}/roby_cycle_overview.png +0 -0
- data/doc/guide/src/tutorial/shell.page +121 -0
- data/doc/guide/src/{basics → tutorial}/summary.page +1 -1
- data/doc/guide/src/tutorial/tasks.page +374 -0
- data/lib/roby.rb +102 -47
- data/lib/roby/actions.rb +17 -0
- data/lib/roby/actions/action.rb +80 -0
- data/lib/roby/actions/interface.rb +45 -0
- data/lib/roby/actions/library.rb +23 -0
- data/lib/roby/actions/models/action.rb +224 -0
- data/lib/roby/actions/models/coordination_action.rb +58 -0
- data/lib/roby/actions/models/interface.rb +22 -0
- data/lib/roby/actions/models/interface_base.rb +294 -0
- data/lib/roby/actions/models/library.rb +12 -0
- data/lib/roby/actions/models/method_action.rb +90 -0
- data/lib/roby/actions/task.rb +114 -0
- data/lib/roby/and_generator.rb +125 -0
- data/lib/roby/app.rb +2795 -829
- data/lib/roby/app/autotest_console_reporter.rb +138 -0
- data/lib/roby/app/base.rb +21 -0
- data/lib/roby/app/cucumber.rb +2 -0
- data/lib/roby/app/cucumber/controller.rb +439 -0
- data/lib/roby/app/cucumber/helpers.rb +280 -0
- data/lib/roby/app/cucumber/world.rb +32 -0
- data/lib/roby/app/debug.rb +136 -0
- data/lib/roby/app/gen.rb +2 -0
- data/lib/roby/app/rake.rb +178 -38
- data/lib/roby/app/robot_config.rb +9 -0
- data/lib/roby/app/robot_names.rb +115 -0
- data/lib/roby/app/run.rb +3 -2
- data/lib/roby/app/scripts.rb +72 -0
- data/lib/roby/app/scripts/autotest.rb +173 -0
- data/lib/roby/app/scripts/display.rb +2 -0
- data/lib/roby/app/scripts/restart.rb +52 -0
- data/lib/roby/app/scripts/results.rb +17 -8
- data/lib/roby/app/scripts/run.rb +155 -24
- data/lib/roby/app/scripts/shell.rb +147 -62
- data/lib/roby/app/scripts/test.rb +107 -22
- data/lib/roby/app/test_reporter.rb +74 -0
- data/lib/roby/app/test_server.rb +159 -0
- data/lib/roby/app/vagrant.rb +47 -0
- data/lib/roby/backports.rb +16 -0
- data/lib/roby/cli/display.rb +190 -0
- data/lib/roby/cli/exceptions.rb +17 -0
- data/lib/roby/cli/gen/actions/class.rb +5 -0
- data/lib/roby/cli/gen/actions/test.rb +6 -0
- data/lib/roby/cli/gen/app/.yardopts +6 -0
- data/lib/roby/cli/gen/app/README.md +28 -0
- data/lib/roby/cli/gen/app/Rakefile +15 -0
- data/{app → lib/roby/cli/gen/app}/config/app.yml +29 -39
- data/lib/roby/cli/gen/app/models/.gitattributes +1 -0
- data/{app → lib/roby/cli/gen/app/scripts}/controllers/.gitattributes +0 -0
- data/{app/data/.gitattributes → lib/roby/cli/gen/app/test/.gitignore} +0 -0
- data/lib/roby/cli/gen/class/class.rb +6 -0
- data/lib/roby/cli/gen/class/test.rb +7 -0
- data/lib/roby/cli/gen/helpers.rb +203 -0
- data/lib/roby/cli/gen/module/module.rb +5 -0
- data/lib/roby/cli/gen/module/test.rb +6 -0
- data/lib/roby/cli/gen/roby_app/config/init.rb +17 -0
- data/lib/roby/cli/gen/roby_app/config/robots/robot.rb +40 -0
- data/lib/roby/cli/gen/task/class.rb +44 -0
- data/lib/roby/cli/gen/task/test.rb +6 -0
- data/lib/roby/cli/gen_main.rb +120 -0
- data/lib/roby/cli/log.rb +276 -0
- data/lib/roby/cli/log/flamegraph.html +499 -0
- data/lib/roby/cli/log/flamegraph_renderer.rb +88 -0
- data/lib/roby/cli/main.rb +153 -0
- data/lib/roby/coordination.rb +60 -0
- data/lib/roby/coordination/action_script.rb +25 -0
- data/lib/roby/coordination/action_state_machine.rb +125 -0
- data/lib/roby/coordination/actions.rb +106 -0
- data/lib/roby/coordination/base.rb +145 -0
- data/lib/roby/coordination/calculus.rb +40 -0
- data/lib/roby/coordination/child.rb +28 -0
- data/lib/roby/coordination/event.rb +29 -0
- data/lib/roby/coordination/fault_handler.rb +25 -0
- data/lib/roby/coordination/fault_handling_task.rb +13 -0
- data/lib/roby/coordination/fault_response_table.rb +110 -0
- data/lib/roby/coordination/models/action_script.rb +64 -0
- data/lib/roby/coordination/models/action_state_machine.rb +224 -0
- data/lib/roby/coordination/models/actions.rb +191 -0
- data/lib/roby/coordination/models/arguments.rb +55 -0
- data/lib/roby/coordination/models/base.rb +176 -0
- data/lib/roby/coordination/models/capture.rb +86 -0
- data/lib/roby/coordination/models/child.rb +35 -0
- data/lib/roby/coordination/models/event.rb +41 -0
- data/lib/roby/coordination/models/exceptions.rb +42 -0
- data/lib/roby/coordination/models/fault_handler.rb +219 -0
- data/lib/roby/coordination/models/fault_response_table.rb +77 -0
- data/lib/roby/coordination/models/root.rb +22 -0
- data/lib/roby/coordination/models/script.rb +283 -0
- data/lib/roby/coordination/models/task.rb +184 -0
- data/lib/roby/coordination/models/task_from_action.rb +50 -0
- data/lib/roby/coordination/models/task_from_as_plan.rb +33 -0
- data/lib/roby/coordination/models/task_from_instanciation_object.rb +31 -0
- data/lib/roby/coordination/models/task_from_variable.rb +27 -0
- data/lib/roby/coordination/models/task_with_dependencies.rb +48 -0
- data/lib/roby/coordination/models/variable.rb +32 -0
- data/lib/roby/coordination/script.rb +200 -0
- data/lib/roby/coordination/script_instruction.rb +12 -0
- data/lib/roby/coordination/task.rb +45 -0
- data/lib/roby/coordination/task_base.rb +69 -0
- data/lib/roby/coordination/task_script.rb +293 -0
- data/lib/roby/coordination/task_state_machine.rb +308 -0
- data/lib/roby/decision_control.rb +33 -21
- data/lib/roby/distributed_object.rb +76 -0
- data/lib/roby/droby.rb +17 -0
- data/lib/roby/droby/droby_id.rb +6 -0
- data/lib/roby/droby/enable.rb +153 -0
- data/lib/roby/droby/event_logger.rb +189 -0
- data/lib/roby/droby/event_logging.rb +57 -0
- data/lib/roby/droby/exceptions.rb +14 -0
- data/lib/roby/droby/identifiable.rb +22 -0
- data/lib/roby/droby/logfile.rb +141 -0
- data/lib/roby/droby/logfile/client.rb +176 -0
- data/lib/roby/droby/logfile/file_format.md +97 -0
- data/lib/roby/droby/logfile/index.rb +117 -0
- data/lib/roby/droby/logfile/reader.rb +139 -0
- data/lib/roby/droby/logfile/server.rb +199 -0
- data/lib/roby/droby/logfile/writer.rb +114 -0
- data/lib/roby/droby/marshal.rb +264 -0
- data/lib/roby/droby/marshallable.rb +12 -0
- data/lib/roby/droby/null_event_logger.rb +25 -0
- data/lib/roby/droby/object_manager.rb +205 -0
- data/lib/roby/droby/peer_id.rb +6 -0
- data/lib/roby/droby/plan_rebuilder.rb +373 -0
- data/lib/roby/droby/rebuilt_plan.rb +160 -0
- data/lib/roby/droby/remote_droby_id.rb +6 -0
- data/lib/roby/droby/timepoints.rb +205 -0
- data/lib/roby/droby/timepoints_ctf.metadata.erb +101 -0
- data/lib/roby/droby/timepoints_ctf.rb +125 -0
- data/lib/roby/droby/v5.rb +14 -0
- data/lib/roby/droby/v5/builtin.rb +120 -0
- data/lib/roby/droby/v5/droby_class.rb +45 -0
- data/lib/roby/droby/v5/droby_constant.rb +81 -0
- data/lib/roby/droby/v5/droby_dump.rb +1026 -0
- data/lib/roby/droby/v5/droby_id.rb +44 -0
- data/lib/roby/droby/v5/droby_model.rb +82 -0
- data/lib/roby/droby/v5/peer_id.rb +10 -0
- data/lib/roby/droby/v5/remote_droby_id.rb +42 -0
- data/lib/roby/event.rb +79 -957
- data/lib/roby/event_constraints.rb +835 -0
- data/lib/roby/event_generator.rb +1047 -0
- data/lib/roby/event_structure/causal_link.rb +6 -0
- data/lib/roby/event_structure/forwarding.rb +6 -0
- data/lib/roby/event_structure/precedence.rb +7 -0
- data/lib/roby/event_structure/signal.rb +8 -0
- data/lib/roby/event_structure/temporal_constraints.rb +640 -0
- data/lib/roby/exceptions.rb +446 -152
- data/lib/roby/executable_plan.rb +549 -0
- data/lib/roby/execution_engine.rb +1997 -950
- data/lib/roby/filter_generator.rb +26 -0
- data/lib/roby/gui/chronicle_view.rb +225 -0
- data/lib/roby/gui/chronicle_widget.rb +925 -0
- data/lib/roby/gui/dot_id.rb +11 -0
- data/lib/roby/gui/exception_view.rb +44 -0
- data/lib/roby/gui/log_display.rb +273 -0
- data/lib/roby/gui/model_views.rb +2 -0
- data/lib/roby/gui/model_views/action_interface.rb +53 -0
- data/lib/roby/gui/model_views/task.rb +47 -0
- data/lib/roby/gui/model_views/task.rhtml +41 -0
- data/lib/roby/gui/object_info_view.rb +89 -0
- data/lib/roby/gui/plan_dot_layout.rb +427 -0
- data/lib/roby/gui/plan_rebuilder_widget.rb +357 -0
- data/lib/roby/gui/qt4_toMSecsSinceEpoch.rb +8 -0
- data/lib/roby/gui/relations_view.rb +278 -0
- data/lib/roby/gui/relations_view/relations.ui +139 -0
- data/lib/roby/gui/relations_view/relations_canvas.rb +1088 -0
- data/lib/roby/gui/relations_view/relations_config.rb +292 -0
- data/lib/roby/gui/relations_view/relations_view.ui +53 -0
- data/lib/roby/gui/scheduler_view.css +24 -0
- data/lib/roby/gui/scheduler_view.rb +46 -0
- data/lib/roby/gui/scheduler_view.rhtml +53 -0
- data/lib/roby/gui/stepping.rb +93 -0
- data/lib/roby/gui/stepping.ui +181 -0
- data/lib/roby/gui/styles.rb +81 -0
- data/lib/roby/gui/task_display_configuration.rb +42 -0
- data/lib/roby/gui/task_state_at.rb +38 -0
- data/lib/roby/hooks.rb +26 -0
- data/lib/roby/interface.rb +136 -469
- data/lib/roby/interface/async.rb +20 -0
- data/lib/roby/interface/async/action_monitor.rb +188 -0
- data/lib/roby/interface/async/interface.rb +498 -0
- data/lib/roby/interface/async/job_monitor.rb +213 -0
- data/lib/roby/interface/async/log.rb +238 -0
- data/lib/roby/interface/async/new_job_listener.rb +79 -0
- data/lib/roby/interface/async/ui_connector.rb +183 -0
- data/lib/roby/interface/client.rb +553 -0
- data/lib/roby/interface/command.rb +24 -0
- data/lib/roby/interface/command_argument.rb +16 -0
- data/lib/roby/interface/command_library.rb +92 -0
- data/lib/roby/interface/droby_channel.rb +174 -0
- data/lib/roby/interface/exceptions.rb +22 -0
- data/lib/roby/interface/interface.rb +655 -0
- data/lib/roby/interface/job.rb +47 -0
- data/lib/roby/interface/rest.rb +10 -0
- data/lib/roby/interface/rest/api.rb +29 -0
- data/lib/roby/interface/rest/helpers.rb +24 -0
- data/lib/roby/interface/rest/server.rb +212 -0
- data/lib/roby/interface/server.rb +154 -0
- data/lib/roby/interface/shell_client.rb +468 -0
- data/lib/roby/interface/shell_subcommand.rb +24 -0
- data/lib/roby/interface/subcommand_client.rb +35 -0
- data/lib/roby/interface/tcp.rb +168 -0
- data/lib/roby/models/arguments.rb +112 -0
- data/lib/roby/models/plan_object.rb +83 -0
- data/lib/roby/models/task.rb +835 -0
- data/lib/roby/models/task_event.rb +62 -0
- data/lib/roby/models/task_service.rb +78 -0
- data/lib/roby/or_generator.rb +88 -0
- data/lib/roby/plan.rb +1751 -864
- data/lib/roby/plan_object.rb +611 -0
- data/lib/roby/plan_service.rb +200 -0
- data/lib/roby/promise.rb +332 -0
- data/lib/roby/queries.rb +23 -0
- data/lib/roby/queries/and_matcher.rb +32 -0
- data/lib/roby/queries/any.rb +27 -0
- data/lib/roby/queries/code_error_matcher.rb +58 -0
- data/lib/roby/queries/event_generator_matcher.rb +9 -0
- data/lib/roby/queries/execution_exception_matcher.rb +165 -0
- data/lib/roby/queries/index.rb +165 -0
- data/lib/roby/queries/localized_error_matcher.rb +149 -0
- data/lib/roby/queries/matcher_base.rb +107 -0
- data/lib/roby/queries/none.rb +27 -0
- data/lib/roby/queries/not_matcher.rb +30 -0
- data/lib/roby/queries/op_matcher.rb +8 -0
- data/lib/roby/queries/or_matcher.rb +30 -0
- data/lib/roby/queries/plan_object_matcher.rb +363 -0
- data/lib/roby/queries/query.rb +188 -0
- data/lib/roby/queries/task_event_generator_matcher.rb +86 -0
- data/lib/roby/queries/task_matcher.rb +344 -0
- data/lib/roby/relations.rb +42 -678
- data/lib/roby/relations/bidirectional_directed_adjacency_graph.rb +492 -0
- data/lib/roby/relations/directed_relation_support.rb +268 -0
- data/lib/roby/relations/event_relation_graph.rb +19 -0
- data/lib/roby/relations/fork_merge_visitor.rb +154 -0
- data/lib/roby/relations/graph.rb +533 -0
- data/lib/roby/relations/models/directed_relation_support.rb +11 -0
- data/lib/roby/relations/models/graph.rb +75 -0
- data/lib/roby/relations/models/task_relation_graph.rb +18 -0
- data/lib/roby/relations/space.rb +380 -0
- data/lib/roby/relations/task_relation_graph.rb +20 -0
- data/lib/roby/robot.rb +85 -38
- data/lib/roby/schedulers/basic.rb +155 -25
- data/lib/roby/schedulers/null.rb +20 -0
- data/lib/roby/schedulers/reporting.rb +31 -0
- data/lib/roby/schedulers/state.rb +129 -0
- data/lib/roby/schedulers/temporal.rb +91 -0
- data/lib/roby/singletons.rb +87 -0
- data/lib/roby/standalone.rb +4 -2
- data/lib/roby/standard_errors.rb +405 -82
- data/lib/roby/state.rb +6 -3
- data/lib/roby/state/conf_model.rb +5 -0
- data/lib/roby/state/events.rb +181 -95
- data/lib/roby/state/goal_model.rb +77 -0
- data/lib/roby/state/open_struct.rb +591 -0
- data/lib/roby/state/open_struct_model.rb +68 -0
- data/lib/roby/state/pos.rb +45 -45
- data/lib/roby/state/shapes.rb +11 -11
- data/lib/roby/state/state_model.rb +303 -0
- data/lib/roby/state/task.rb +43 -0
- data/lib/roby/support.rb +88 -148
- data/lib/roby/task.rb +1361 -1750
- data/lib/roby/task_arguments.rb +428 -0
- data/lib/roby/task_event.rb +127 -0
- data/lib/roby/task_event_generator.rb +337 -0
- data/lib/roby/task_service.rb +6 -0
- data/lib/roby/task_structure/conflicts.rb +104 -0
- data/lib/roby/task_structure/dependency.rb +932 -0
- data/lib/roby/task_structure/error_handling.rb +118 -0
- data/lib/roby/task_structure/executed_by.rb +234 -0
- data/lib/roby/task_structure/planned_by.rb +90 -0
- data/lib/roby/tasks/aggregator.rb +37 -0
- data/lib/roby/tasks/external_process.rb +275 -0
- data/lib/roby/tasks/group.rb +27 -0
- data/lib/roby/tasks/null.rb +19 -0
- data/lib/roby/tasks/parallel.rb +43 -0
- data/lib/roby/tasks/sequence.rb +88 -0
- data/lib/roby/tasks/simple.rb +21 -0
- data/lib/roby/{thread_task.rb → tasks/thread.rb} +50 -24
- data/lib/roby/tasks/timeout.rb +17 -0
- data/lib/roby/tasks/virtual.rb +55 -0
- data/lib/roby/template_plan.rb +7 -0
- data/lib/roby/test/aruba_minitest.rb +74 -0
- data/lib/roby/test/assertion.rb +16 -0
- data/lib/roby/test/assertions.rb +490 -0
- data/lib/roby/test/common.rb +368 -591
- data/lib/roby/test/dsl.rb +149 -0
- data/lib/roby/test/error.rb +18 -0
- data/lib/roby/test/event_reporter.rb +83 -0
- data/lib/roby/test/execution_expectations.rb +1134 -0
- data/lib/roby/test/expect_execution.rb +151 -0
- data/lib/roby/test/minitest_helpers.rb +166 -0
- data/lib/roby/test/roby_app_helpers.rb +200 -0
- data/lib/roby/test/run_planners.rb +155 -0
- data/lib/roby/test/self.rb +112 -0
- data/lib/roby/test/spec.rb +198 -0
- data/lib/roby/test/tasks/empty_task.rb +4 -4
- data/lib/roby/test/tasks/goto.rb +28 -27
- data/lib/roby/test/teardown_plans.rb +100 -0
- data/lib/roby/test/testcase.rb +239 -307
- data/lib/roby/test/tools.rb +159 -155
- data/lib/roby/test/validate_state_machine.rb +75 -0
- data/lib/roby/transaction.rb +1125 -0
- data/lib/roby/transaction/event_generator_proxy.rb +63 -0
- data/lib/roby/transaction/plan_object_proxy.rb +99 -0
- data/lib/roby/transaction/plan_service_proxy.rb +43 -0
- data/lib/roby/transaction/proxying.rb +120 -0
- data/lib/roby/transaction/task_event_generator_proxy.rb +19 -0
- data/lib/roby/transaction/task_proxy.rb +135 -0
- data/lib/roby/until_generator.rb +30 -0
- data/lib/roby/version.rb +5 -0
- data/lib/roby/yard.rb +169 -0
- data/lib/yard-roby.rb +1 -0
- data/manifest.xml +32 -6
- data/roby.gemspec +59 -0
- metadata +788 -587
- data/Manifest.txt +0 -321
- data/NOTES +0 -4
- data/README.txt +0 -166
- data/TODO.txt +0 -146
- data/app/README.txt +0 -24
- data/app/Rakefile +0 -8
- data/app/config/ROBOT.rb +0 -5
- data/app/config/init.rb +0 -33
- data/app/config/roby.yml +0 -3
- data/app/controllers/ROBOT.rb +0 -2
- data/app/planners/ROBOT/main.rb +0 -6
- data/app/planners/main.rb +0 -5
- data/app/scripts/distributed +0 -3
- data/app/scripts/generate/bookmarks +0 -3
- data/app/scripts/replay +0 -3
- data/app/scripts/results +0 -3
- data/app/scripts/run +0 -3
- data/app/scripts/server +0 -3
- data/app/scripts/shell +0 -3
- data/app/scripts/test +0 -3
- data/app/tasks/.gitattributes +0 -0
- data/app/tasks/ROBOT/.gitattributes +0 -0
- data/bin/roby-shell +0 -25
- data/doc/guide/src/basics/app.page +0 -139
- data/doc/guide/src/basics/index.page +0 -11
- 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_5.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/relations_display.page +0 -203
- data/doc/guide/src/basics/shell.page +0 -102
- data/doc/guide/src/default.css +0 -319
- data/doc/guide/src/introduction/index.page +0 -29
- data/doc/guide/src/introduction/publications.page +0 -14
- data/doc/guide/src/relations/dependency.page +0 -89
- data/doc/guide/src/relations/index.page +0 -12
- data/ext/droby/dump.cc +0 -175
- data/ext/droby/extconf.rb +0 -3
- data/ext/graph/algorithm.cc +0 -746
- data/ext/graph/extconf.rb +0 -7
- data/ext/graph/graph.cc +0 -575
- data/ext/graph/graph.hh +0 -183
- data/ext/graph/iterator_sequence.hh +0 -102
- data/ext/graph/undirected_dfs.hh +0 -226
- data/ext/graph/undirected_graph.hh +0 -421
- data/lib/roby/app/scripts/generate/bookmarks.rb +0 -162
- data/lib/roby/app/scripts/replay.rb +0 -31
- data/lib/roby/app/scripts/server.rb +0 -18
- data/lib/roby/basic_object.rb +0 -151
- data/lib/roby/config.rb +0 -14
- data/lib/roby/distributed.rb +0 -36
- data/lib/roby/distributed/base.rb +0 -448
- data/lib/roby/distributed/communication.rb +0 -875
- data/lib/roby/distributed/connection_space.rb +0 -616
- data/lib/roby/distributed/distributed_object.rb +0 -206
- data/lib/roby/distributed/drb.rb +0 -62
- data/lib/roby/distributed/notifications.rb +0 -531
- data/lib/roby/distributed/peer.rb +0 -555
- data/lib/roby/distributed/protocol.rb +0 -529
- data/lib/roby/distributed/proxy.rb +0 -343
- data/lib/roby/distributed/subscription.rb +0 -311
- data/lib/roby/distributed/transaction.rb +0 -498
- data/lib/roby/external_process_task.rb +0 -225
- data/lib/roby/graph.rb +0 -160
- data/lib/roby/log.rb +0 -3
- data/lib/roby/log/chronicle.rb +0 -303
- data/lib/roby/log/console.rb +0 -74
- data/lib/roby/log/data_stream.rb +0 -275
- data/lib/roby/log/dot.rb +0 -279
- data/lib/roby/log/event_stream.rb +0 -161
- data/lib/roby/log/file.rb +0 -396
- data/lib/roby/log/gui/basic_display.ui +0 -83
- data/lib/roby/log/gui/basic_display_ui.rb +0 -89
- data/lib/roby/log/gui/chronicle.rb +0 -26
- data/lib/roby/log/gui/chronicle_view.rb +0 -40
- data/lib/roby/log/gui/chronicle_view.ui +0 -70
- data/lib/roby/log/gui/chronicle_view_ui.rb +0 -90
- data/lib/roby/log/gui/data_displays.rb +0 -171
- data/lib/roby/log/gui/data_displays.ui +0 -155
- data/lib/roby/log/gui/data_displays_ui.rb +0 -146
- data/lib/roby/log/gui/notifications.rb +0 -26
- data/lib/roby/log/gui/relations.rb +0 -269
- data/lib/roby/log/gui/relations.ui +0 -123
- data/lib/roby/log/gui/relations_ui.rb +0 -120
- data/lib/roby/log/gui/relations_view.rb +0 -185
- data/lib/roby/log/gui/relations_view.ui +0 -149
- data/lib/roby/log/gui/relations_view_ui.rb +0 -144
- data/lib/roby/log/gui/replay.rb +0 -366
- data/lib/roby/log/gui/replay_controls.rb +0 -206
- data/lib/roby/log/gui/replay_controls.ui +0 -282
- data/lib/roby/log/gui/replay_controls_ui.rb +0 -249
- data/lib/roby/log/gui/runtime.rb +0 -130
- data/lib/roby/log/hooks.rb +0 -186
- data/lib/roby/log/logger.rb +0 -203
- data/lib/roby/log/notifications.rb +0 -244
- data/lib/roby/log/plan_rebuilder.rb +0 -468
- data/lib/roby/log/relations.rb +0 -1084
- data/lib/roby/log/server.rb +0 -547
- data/lib/roby/log/sqlite.rb +0 -47
- data/lib/roby/log/timings.rb +0 -233
- data/lib/roby/plan-object.rb +0 -371
- data/lib/roby/planning.rb +0 -13
- data/lib/roby/planning/loops.rb +0 -309
- data/lib/roby/planning/model.rb +0 -1012
- data/lib/roby/planning/task.rb +0 -180
- data/lib/roby/query.rb +0 -655
- data/lib/roby/relations/conflicts.rb +0 -67
- data/lib/roby/relations/dependency.rb +0 -358
- data/lib/roby/relations/ensured.rb +0 -19
- data/lib/roby/relations/error_handling.rb +0 -22
- data/lib/roby/relations/events.rb +0 -7
- data/lib/roby/relations/executed_by.rb +0 -208
- data/lib/roby/relations/influence.rb +0 -10
- data/lib/roby/relations/planned_by.rb +0 -63
- data/lib/roby/state/information.rb +0 -55
- data/lib/roby/state/state.rb +0 -367
- data/lib/roby/task-operations.rb +0 -186
- data/lib/roby/task_index.rb +0 -80
- data/lib/roby/test/distributed.rb +0 -230
- data/lib/roby/test/tasks/simple_task.rb +0 -23
- data/lib/roby/transactions.rb +0 -507
- data/lib/roby/transactions/proxy.rb +0 -325
- data/plugins/fault_injection/History.txt +0 -4
- data/plugins/fault_injection/README.txt +0 -34
- data/plugins/fault_injection/Rakefile +0 -12
- data/plugins/fault_injection/TODO.txt +0 -0
- data/plugins/fault_injection/app.rb +0 -52
- data/plugins/fault_injection/fault_injection.rb +0 -89
- data/plugins/fault_injection/test/test_fault_injection.rb +0 -78
- data/plugins/subsystems/README.txt +0 -37
- data/plugins/subsystems/Rakefile +0 -13
- data/plugins/subsystems/app.rb +0 -182
- data/plugins/subsystems/test/app/README +0 -24
- data/plugins/subsystems/test/app/Rakefile +0 -8
- data/plugins/subsystems/test/app/config/app.yml +0 -71
- data/plugins/subsystems/test/app/config/init.rb +0 -12
- data/plugins/subsystems/test/app/config/roby.yml +0 -3
- data/plugins/subsystems/test/app/planners/main.rb +0 -20
- data/plugins/subsystems/test/app/scripts/distributed +0 -3
- data/plugins/subsystems/test/app/scripts/replay +0 -3
- data/plugins/subsystems/test/app/scripts/results +0 -3
- data/plugins/subsystems/test/app/scripts/run +0 -3
- data/plugins/subsystems/test/app/scripts/server +0 -3
- data/plugins/subsystems/test/app/scripts/shell +0 -3
- data/plugins/subsystems/test/app/scripts/test +0 -3
- data/plugins/subsystems/test/app/tasks/services.rb +0 -15
- data/plugins/subsystems/test/test_subsystems.rb +0 -78
- data/test/distributed/test_communication.rb +0 -195
- data/test/distributed/test_connection.rb +0 -284
- data/test/distributed/test_execution.rb +0 -378
- data/test/distributed/test_mixed_plan.rb +0 -341
- data/test/distributed/test_plan_notifications.rb +0 -238
- data/test/distributed/test_protocol.rb +0 -525
- data/test/distributed/test_query.rb +0 -106
- data/test/distributed/test_remote_plan.rb +0 -491
- data/test/distributed/test_transaction.rb +0 -466
- data/test/mockups/external_process +0 -28
- data/test/mockups/tasks.rb +0 -27
- data/test/planning/test_loops.rb +0 -432
- data/test/planning/test_model.rb +0 -427
- data/test/planning/test_task.rb +0 -126
- data/test/relations/test_conflicts.rb +0 -42
- data/test/relations/test_dependency.rb +0 -324
- data/test/relations/test_ensured.rb +0 -38
- data/test/relations/test_executed_by.rb +0 -224
- data/test/relations/test_planned_by.rb +0 -56
- data/test/suite_core.rb +0 -29
- data/test/suite_distributed.rb +0 -10
- data/test/suite_planning.rb +0 -4
- data/test/suite_relations.rb +0 -8
- data/test/tasks/test_external_process.rb +0 -126
- data/test/tasks/test_thread_task.rb +0 -70
- data/test/test_bgl.rb +0 -528
- data/test/test_event.rb +0 -969
- data/test/test_exceptions.rb +0 -591
- data/test/test_execution_engine.rb +0 -987
- data/test/test_gui.rb +0 -20
- data/test/test_interface.rb +0 -43
- data/test/test_log.rb +0 -125
- data/test/test_log_server.rb +0 -133
- data/test/test_plan.rb +0 -418
- data/test/test_query.rb +0 -424
- data/test/test_relations.rb +0 -260
- data/test/test_state.rb +0 -432
- data/test/test_support.rb +0 -16
- data/test/test_task.rb +0 -1181
- data/test/test_testcase.rb +0 -138
- data/test/test_transactions.rb +0 -610
- data/test/test_transactions_proxy.rb +0 -216
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
module Roby
|
|
2
|
+
# A plan service represents a "place" in the plan. I.e. it initially is
|
|
3
|
+
# attached to a given task instance, but its attachment will move when the
|
|
4
|
+
# task is replaced by another one, thus allowing to track a task that
|
|
5
|
+
# performs a given service for the system.
|
|
6
|
+
#
|
|
7
|
+
# It forwards method calls to the underlying task
|
|
8
|
+
class PlanService
|
|
9
|
+
extend Transaction::Proxying::Cache
|
|
10
|
+
|
|
11
|
+
# The underlying task
|
|
12
|
+
#
|
|
13
|
+
# @return [Roby::Task]
|
|
14
|
+
attr_reader :task
|
|
15
|
+
# Set of blocks that will be called when the service itself is finalized
|
|
16
|
+
#
|
|
17
|
+
# @see #when_finalized
|
|
18
|
+
attr_reader :finalization_handlers
|
|
19
|
+
# The set of event handlers that have been defined for this service
|
|
20
|
+
#
|
|
21
|
+
# It is a mapping from a symbol (that represents the event name) to a
|
|
22
|
+
# set of procs that represent the handlers themselves
|
|
23
|
+
#
|
|
24
|
+
# @see #on
|
|
25
|
+
attr_reader :event_handlers
|
|
26
|
+
# The set of handlers for replacments
|
|
27
|
+
#
|
|
28
|
+
# @see #on_replacement
|
|
29
|
+
attr_reader :replacement_handlers
|
|
30
|
+
# The set of handlers for mission/permanent status change
|
|
31
|
+
attr_reader :plan_status_handlers
|
|
32
|
+
|
|
33
|
+
def initialize(task)
|
|
34
|
+
@event_handlers = Hash.new
|
|
35
|
+
@finalization_handlers = Array.new
|
|
36
|
+
@replacement_handlers = Array.new
|
|
37
|
+
@plan_status_handlers = Array.new
|
|
38
|
+
self.task = task
|
|
39
|
+
task.plan.add_plan_service(self)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def initialize_copy(source)
|
|
43
|
+
super
|
|
44
|
+
|
|
45
|
+
@event_handlers = source.event_handlers.dup
|
|
46
|
+
@finalization_handlers = source.finalization_handlers.dup
|
|
47
|
+
@replacement_handlers = source.replacement_handlers.dup
|
|
48
|
+
@plan_status_handlers = source.plan_status_handlers.dup
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# True if this plan service instance is a transaction proxy, i.e.
|
|
52
|
+
# modifies an already existing service in the frame of a transaction
|
|
53
|
+
def transaction_proxy?
|
|
54
|
+
false
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
alias __to_s__ to_s
|
|
58
|
+
def to_s # :nodoc:
|
|
59
|
+
"#<service #{task.to_s}>"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Register a callback that should be called when the underlying task is
|
|
63
|
+
# replaced
|
|
64
|
+
#
|
|
65
|
+
# @yield old, new
|
|
66
|
+
def on_replacement(&block)
|
|
67
|
+
replacement_handlers << block
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Registers a callback that is called when the task's mission/permanent
|
|
71
|
+
# status changes
|
|
72
|
+
#
|
|
73
|
+
# @yieldparam [Symbol] status one of :mission, :permanent or :normal
|
|
74
|
+
def on_plan_status_change(initial: true, &block)
|
|
75
|
+
plan_status_handlers << block
|
|
76
|
+
if initial
|
|
77
|
+
current_status =
|
|
78
|
+
if task.plan.mission_task?(task)
|
|
79
|
+
:mission
|
|
80
|
+
elsif task.plan.permanent_task?(task)
|
|
81
|
+
:permanent
|
|
82
|
+
else :normal
|
|
83
|
+
end
|
|
84
|
+
block.call(current_status)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Called to notify about a plan status change for the underlying task
|
|
89
|
+
#
|
|
90
|
+
# @see on_plan_status_change
|
|
91
|
+
def notify_task_status_change(new_status)
|
|
92
|
+
plan_status_handlers.each do |h|
|
|
93
|
+
h.call(new_status)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Change the underlying task
|
|
98
|
+
def task=(new_task)
|
|
99
|
+
replacement_handlers.each do |h|
|
|
100
|
+
h.call(task, new_task)
|
|
101
|
+
end
|
|
102
|
+
@task = new_task
|
|
103
|
+
|
|
104
|
+
# Register event handlers for all events that have a definition
|
|
105
|
+
event_handlers.each_key do |event|
|
|
106
|
+
new_task.event(event).on(on_replace: :drop, &method(:__handle_event__))
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Event handler that is actually added to the tasks, to implement the
|
|
111
|
+
# event handlers
|
|
112
|
+
def __handle_event__(event) # :nodoc:
|
|
113
|
+
# Only proceeed if the event's origin is the task that currently
|
|
114
|
+
# represents that service
|
|
115
|
+
return if event.task != task
|
|
116
|
+
|
|
117
|
+
# And call the handlers
|
|
118
|
+
event_handlers[event.generator.symbol].each do |handler|
|
|
119
|
+
handler.call(event)
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Called by the plan when the service is finalized
|
|
124
|
+
def finalized!
|
|
125
|
+
if task.plan.executable?
|
|
126
|
+
finalization_handlers.each do |h|
|
|
127
|
+
h.call
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Defines a finalization handler for this service
|
|
133
|
+
#
|
|
134
|
+
# This handler will be called when the service itself is finalized
|
|
135
|
+
def when_finalized(&block)
|
|
136
|
+
finalization_handlers << block
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Defines an event handler for this service
|
|
140
|
+
#
|
|
141
|
+
# This event handler will only be called if +symbol+ is emitted by the
|
|
142
|
+
# task that currently provides this service.
|
|
143
|
+
#
|
|
144
|
+
# For instance, if you do
|
|
145
|
+
#
|
|
146
|
+
# service = PlanService.get(t)
|
|
147
|
+
# service.on(:success) do
|
|
148
|
+
# STDERR.puts "message"
|
|
149
|
+
# end
|
|
150
|
+
# plan.replace(t, t2)
|
|
151
|
+
#
|
|
152
|
+
# Then, before the replacement, 'message' is displayed if t emits
|
|
153
|
+
# :success. After the replacement, it will be displayed if t2 emits
|
|
154
|
+
# :success, and will not be displayed if t does.
|
|
155
|
+
def on(event, &block)
|
|
156
|
+
check_arity(block, 1)
|
|
157
|
+
event = event.to_sym
|
|
158
|
+
if event_handlers.has_key?(event)
|
|
159
|
+
event_handlers[event] << block
|
|
160
|
+
else
|
|
161
|
+
task.event(event).on(on_replace: :drop, &method(:__handle_event__))
|
|
162
|
+
(event_handlers[event] = Array.new) << block
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# Returns a plan service for +task+. If a service is already defined for
|
|
167
|
+
# +task+, it will return it.
|
|
168
|
+
def self.get(task)
|
|
169
|
+
if service = task.plan.find_plan_service(task)
|
|
170
|
+
service
|
|
171
|
+
else
|
|
172
|
+
new(task)
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def respond_to_missing?(m, include_private)
|
|
177
|
+
task.respond_to?(m)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# Forwards all calls to {task}
|
|
181
|
+
def method_missing(*args, &block) # :nodoc:
|
|
182
|
+
task.public_send(*args, &block)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Returns the underlying task
|
|
186
|
+
#
|
|
187
|
+
# @see task
|
|
188
|
+
def to_task
|
|
189
|
+
task
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def kind_of?(*args)
|
|
193
|
+
super || task.kind_of?(*args)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def create_transaction_proxy(transaction)
|
|
197
|
+
transaction.create_and_register_proxy_plan_service(self)
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|
data/lib/roby/promise.rb
ADDED
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
module Roby
|
|
2
|
+
# An extension to {Concurrent::Promise} that is aware of the mixed thread/event
|
|
3
|
+
# loop nature of Roby
|
|
4
|
+
#
|
|
5
|
+
# Use {ExecutionEngine#promise} to create one
|
|
6
|
+
#
|
|
7
|
+
# {#on_success} and {#rescue} gain an in_engine argument, which decides
|
|
8
|
+
# whether the given block should be executed by the underlying execution
|
|
9
|
+
# engine's or not. It is true by default. Note that {#then} is not overriden
|
|
10
|
+
#
|
|
11
|
+
# This promise implementation has no graph capabilities. The execution must
|
|
12
|
+
# be a pipeline, and a whole pipeline is represented by a single Promise.
|
|
13
|
+
# State predicates such as #fulfilled? or #rejected? are valid for the whole
|
|
14
|
+
# pipeline. There is no way to handle errors for only parts of the pipeline.
|
|
15
|
+
class Promise
|
|
16
|
+
class AlreadyHasErrorHandler < RuntimeError; end
|
|
17
|
+
class NotComplete < RuntimeError; end
|
|
18
|
+
|
|
19
|
+
# The execution engine we execute on
|
|
20
|
+
attr_reader :execution_engine
|
|
21
|
+
# The Promise object from concurrent-ruby that handles the nominal part
|
|
22
|
+
# of the execution
|
|
23
|
+
attr_reader :promise
|
|
24
|
+
# A description text for debugging purposes
|
|
25
|
+
attr_reader :description
|
|
26
|
+
# The pipeline itself
|
|
27
|
+
#
|
|
28
|
+
# @return [Array<PipelineElement>]
|
|
29
|
+
attr_reader :pipeline
|
|
30
|
+
# The pipeline that will be executed if an error happens in {#pipeline}
|
|
31
|
+
#
|
|
32
|
+
# @return [Array<PipelineElement>]
|
|
33
|
+
attr_reader :error_pipeline
|
|
34
|
+
|
|
35
|
+
def initialize(execution_engine, executor: execution_engine.thread_pool, description: "promise", &block)
|
|
36
|
+
@execution_engine = execution_engine
|
|
37
|
+
execution_engine.waiting_work << self
|
|
38
|
+
@description = description
|
|
39
|
+
|
|
40
|
+
@pipeline = Array.new
|
|
41
|
+
@error_pipeline = Array.new
|
|
42
|
+
@promise = Concurrent::Promise.new(executor: executor, &method(:run_pipeline))
|
|
43
|
+
@current_element = Concurrent::AtomicReference.new
|
|
44
|
+
if block
|
|
45
|
+
self.then(&block)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Whether this is a null promise
|
|
50
|
+
def null?
|
|
51
|
+
false
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Whether this promise does have elements
|
|
55
|
+
def empty?
|
|
56
|
+
@pipeline.empty?
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# The description element being currently executed
|
|
60
|
+
#
|
|
61
|
+
# @return [String,nil]
|
|
62
|
+
def current_element
|
|
63
|
+
@current_element.get
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Representation of one element in the pipeline
|
|
67
|
+
PipelineElement = Struct.new :description, :run_in_engine, :callback
|
|
68
|
+
|
|
69
|
+
# @api private
|
|
70
|
+
#
|
|
71
|
+
# Internal implementation of the pipeline. This holds a thread until it
|
|
72
|
+
# is finished - there's no point in giving the thread back between the
|
|
73
|
+
# steps in the pipeline, given how the promises are used in Roby (to
|
|
74
|
+
# avoid freezing due to blocking calls)
|
|
75
|
+
def run_pipeline(*state)
|
|
76
|
+
Thread.current.name = "run_promises"
|
|
77
|
+
|
|
78
|
+
execution_engine.log_timepoint_group "#{description}" do
|
|
79
|
+
begin
|
|
80
|
+
run_pipeline_elements(self.pipeline, state)
|
|
81
|
+
rescue Exception => exception
|
|
82
|
+
run_pipeline_elements(self.error_pipeline, exception, propagate_state: false)
|
|
83
|
+
raise Failure.new(exception)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
ensure
|
|
87
|
+
@current_element.set(nil)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# @api private
|
|
91
|
+
#
|
|
92
|
+
# Run one of {#pipeline} or {#error_pipeline}
|
|
93
|
+
def run_pipeline_elements(pipeline, state, propagate_state: true)
|
|
94
|
+
pipeline = pipeline.dup
|
|
95
|
+
while !pipeline.empty?
|
|
96
|
+
state = run_one_pipeline_segment(pipeline, state, false, propagate_state: propagate_state)
|
|
97
|
+
if !pipeline.empty?
|
|
98
|
+
state = execution_engine.log_timepoint_group "#{description}:execute_in_engine" do
|
|
99
|
+
execution_engine.execute(type: :propagation) do
|
|
100
|
+
run_one_pipeline_segment(pipeline, state, true, propagate_state: propagate_state)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
state
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# @api private
|
|
109
|
+
#
|
|
110
|
+
# Encapsulation of an exception raised by a callback
|
|
111
|
+
#
|
|
112
|
+
# For whatever reason, the concurrent-ruby developers decided that a
|
|
113
|
+
# non-RuntimeError would be fatal to the promise (not be handled
|
|
114
|
+
# "normally").
|
|
115
|
+
#
|
|
116
|
+
# Roby never had such a constraint, so that's dangerous here.
|
|
117
|
+
# Encapsulate an exception in Failure to pass it out of the
|
|
118
|
+
# concurrent-ruby promise.
|
|
119
|
+
class Failure < RuntimeError
|
|
120
|
+
attr_reader :actual_exception
|
|
121
|
+
def initialize(error)
|
|
122
|
+
@actual_exception = error
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# @api private
|
|
127
|
+
#
|
|
128
|
+
# Helper method for {#run_pipeline_elements}, to run a sequence of
|
|
129
|
+
# elements in a pipeline that have the same run_in_engine?
|
|
130
|
+
def run_one_pipeline_segment(pipeline, state, in_engine, propagate_state: true)
|
|
131
|
+
while (element = pipeline.first) && !(in_engine ^ element.run_in_engine)
|
|
132
|
+
pipeline.shift
|
|
133
|
+
@current_element.set(element.description)
|
|
134
|
+
new_state = execution_engine.log_timepoint_group "#{element.description} in_engine=#{element.run_in_engine}" do
|
|
135
|
+
element.callback.call(state)
|
|
136
|
+
end
|
|
137
|
+
state = new_state if propagate_state
|
|
138
|
+
end
|
|
139
|
+
state
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def to_s
|
|
143
|
+
"#<Roby::Promise #{description}>"
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def pretty_print(pp)
|
|
147
|
+
description = self.description
|
|
148
|
+
pp.text "Roby::Promise(#{description}"
|
|
149
|
+
if current_element = self.current_element
|
|
150
|
+
pp.text ", currently: #{current_element})"
|
|
151
|
+
else
|
|
152
|
+
pp.text ")"
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
pipeline.each do |element|
|
|
156
|
+
pp.nest(2) do
|
|
157
|
+
pp.text "."
|
|
158
|
+
pp.breakable
|
|
159
|
+
if element.run_in_engine
|
|
160
|
+
pp.text "on_success(#{element.description})"
|
|
161
|
+
else
|
|
162
|
+
pp.text "then(#{element.description})"
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
error_pipeline.each do |element|
|
|
167
|
+
pp.nest(2) do
|
|
168
|
+
pp.text "."
|
|
169
|
+
pp.breakable
|
|
170
|
+
pp.text "on_error(#{element.description}, in_engine: #{element.run_in_engine})"
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# Whether self already has an error handler
|
|
176
|
+
#
|
|
177
|
+
# Unlike {Concurrent::Promise}, {Roby::Promise} objects can only have
|
|
178
|
+
# one error handler
|
|
179
|
+
def has_error_handler?
|
|
180
|
+
!error_pipeline.empty?
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Queue a block at the beginning of the pipeline
|
|
184
|
+
def before(description: "#{self.description}.before", in_engine: true, &block)
|
|
185
|
+
pipeline.unshift PipelineElement.new(description, in_engine, block)
|
|
186
|
+
self
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# Schedule execution of a block on the success of self
|
|
190
|
+
#
|
|
191
|
+
# @param [String] description a textual description useful for debugging
|
|
192
|
+
# @param [Boolean] in_engine whether the block should be executed within
|
|
193
|
+
# the underlying {ExecutionEngine}, a.k.a. in the main thread, or
|
|
194
|
+
# scheduled in a separate thread.
|
|
195
|
+
def on_success(description: "#{self.description}.on_success[#{pipeline.size}]", in_engine: true, &block)
|
|
196
|
+
pipeline << PipelineElement.new(description, in_engine, block)
|
|
197
|
+
self
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# Schedule execution of a block if self or one of its parents failed
|
|
201
|
+
#
|
|
202
|
+
# @param [String] description a textual description useful for debugging
|
|
203
|
+
# @param [Boolean] in_engine whether the block should be executed within
|
|
204
|
+
# the underlying {ExecutionEngine}, a.k.a. in the main thread, or
|
|
205
|
+
# scheduled in a separate thread.
|
|
206
|
+
# @yieldparam [Object] reason the exception that caused the failure,
|
|
207
|
+
# usually an exception that was raised by one of the promise blocks.
|
|
208
|
+
def on_error(description: "#{self.description}.on_error", in_engine: true, &block)
|
|
209
|
+
error_pipeline << PipelineElement.new(description, in_engine, block)
|
|
210
|
+
self
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# Alias for {#on_success}, but defaulting to execution as a separate
|
|
214
|
+
# thread
|
|
215
|
+
def then(description: "#{self.description}.then[#{pipeline.size}]", &block)
|
|
216
|
+
on_success(description: description, in_engine: false, &block)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def fail(exception = StandardError)
|
|
220
|
+
promise.fail(exception)
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def execute
|
|
224
|
+
promise.execute
|
|
225
|
+
self
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def unscheduled?
|
|
229
|
+
promise.unscheduled?
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def pending?
|
|
233
|
+
promise.pending?
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def complete?
|
|
237
|
+
promise.complete?
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def fulfilled?
|
|
241
|
+
promise.fulfilled?
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def rejected?
|
|
245
|
+
promise.rejected?
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def wait
|
|
249
|
+
promise.wait
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def value(timeout = nil)
|
|
253
|
+
if promise.complete?
|
|
254
|
+
promise.value(timeout)
|
|
255
|
+
else
|
|
256
|
+
raise NotComplete, "cannot call #value on a non-complete promise"
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def value!(timeout = nil)
|
|
261
|
+
if promise.complete?
|
|
262
|
+
promise.value!(timeout)
|
|
263
|
+
else
|
|
264
|
+
raise NotComplete, "cannot call #value on a non-complete promise"
|
|
265
|
+
end
|
|
266
|
+
rescue Failure => e
|
|
267
|
+
raise e.actual_exception
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
# Returns the exception that caused the promise to be rejected
|
|
271
|
+
def reason
|
|
272
|
+
if failure = promise.reason
|
|
273
|
+
failure.actual_exception
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
# The promise's execution state
|
|
278
|
+
def state
|
|
279
|
+
promise.state
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
# Register a block that will be called on this promise's termination
|
|
283
|
+
#
|
|
284
|
+
# @yieldparam [Time] time the termination time
|
|
285
|
+
# @yieldparam [Object,nil] result the promise result if it finished
|
|
286
|
+
# execution successfully, or nil if an exception was raised
|
|
287
|
+
# @yieldparam [Object,nil] reason the exception that terminated this
|
|
288
|
+
# promise if it failed, or nil if it finished successfully
|
|
289
|
+
def add_observer(&block)
|
|
290
|
+
promise.add_observer(&block)
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
def self.null(value = nil)
|
|
294
|
+
Null.new(value)
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
# A null object for {Promise}
|
|
298
|
+
class Null
|
|
299
|
+
def initialize(value = nil)
|
|
300
|
+
@creation_time = Time.now
|
|
301
|
+
@value = value
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def null?; true end
|
|
305
|
+
def empty?; true end
|
|
306
|
+
|
|
307
|
+
def before(*); raise NullPromise, "attempting to add a step on a null promise" end
|
|
308
|
+
def on_success(*); raise NullPromise, "attempting to add a step on a null promise" end
|
|
309
|
+
def on_error(*); raise NullPromise, "attempting to add a step on a null promise" end
|
|
310
|
+
def then(*); raise NullPromise, "attempting to add a step on a null promise" end
|
|
311
|
+
|
|
312
|
+
def fail(*); raise NullPromise, "a null promise cannot fail" end
|
|
313
|
+
def execute; self end
|
|
314
|
+
def unscheduled?; false end
|
|
315
|
+
def pending?; false end
|
|
316
|
+
def complete?; true end
|
|
317
|
+
def fulfilled?; true end
|
|
318
|
+
def rejected?; false end
|
|
319
|
+
def wait; end
|
|
320
|
+
|
|
321
|
+
def value(*); @value end
|
|
322
|
+
def value!(*); @value end
|
|
323
|
+
def reason; end
|
|
324
|
+
def state; :fulfilled end
|
|
325
|
+
|
|
326
|
+
def add_observer(&block)
|
|
327
|
+
block.call(@creation_time, value, nil)
|
|
328
|
+
end
|
|
329
|
+
end
|
|
330
|
+
end
|
|
331
|
+
end
|
|
332
|
+
|