roby 0.7.3 → 0.8.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 (236) hide show
  1. data/History.txt +7 -5
  2. data/Manifest.txt +91 -16
  3. data/README.txt +24 -24
  4. data/Rakefile +92 -64
  5. data/app/config/app.yml +42 -43
  6. data/app/config/init.rb +26 -0
  7. data/benchmark/alloc_misc.rb +123 -0
  8. data/benchmark/discovery_latency.rb +67 -0
  9. data/benchmark/garbage_collection.rb +48 -0
  10. data/benchmark/genom.rb +31 -0
  11. data/benchmark/transactions.rb +62 -0
  12. data/bin/roby +1 -1
  13. data/bin/roby-log +16 -6
  14. data/doc/guide/.gitignore +2 -0
  15. data/doc/guide/config.yaml +34 -0
  16. data/doc/guide/ext/init.rb +14 -0
  17. data/doc/guide/ext/previous_next.rb +40 -0
  18. data/doc/guide/ext/rdoc_links.rb +33 -0
  19. data/doc/guide/index.rdoc +16 -0
  20. data/doc/guide/overview.rdoc +62 -0
  21. data/doc/guide/plan_modifications.rdoc +67 -0
  22. data/doc/guide/src/abstraction/achieve_with.page +8 -0
  23. data/doc/guide/src/abstraction/forwarding.page +8 -0
  24. data/doc/guide/src/abstraction/hierarchy.page +19 -0
  25. data/doc/guide/src/abstraction/index.page +28 -0
  26. data/doc/guide/src/abstraction/task_models.page +13 -0
  27. data/doc/guide/src/basics.template +6 -0
  28. data/doc/guide/src/basics/app.page +139 -0
  29. data/doc/guide/src/basics/code_examples.page +33 -0
  30. data/doc/guide/src/basics/dry.page +69 -0
  31. data/doc/guide/src/basics/errors.page +443 -0
  32. data/doc/guide/src/basics/events.page +179 -0
  33. data/doc/guide/src/basics/hierarchy.page +275 -0
  34. data/doc/guide/src/basics/index.page +11 -0
  35. data/doc/guide/src/basics/log_replay/goForward_1.png +0 -0
  36. data/doc/guide/src/basics/log_replay/goForward_2.png +0 -0
  37. data/doc/guide/src/basics/log_replay/goForward_3.png +0 -0
  38. data/doc/guide/src/basics/log_replay/goForward_4.png +0 -0
  39. data/doc/guide/src/basics/log_replay/goForward_5.png +0 -0
  40. data/doc/guide/src/basics/log_replay/hierarchy_error_1.png +0 -0
  41. data/doc/guide/src/basics/log_replay/hierarchy_error_2.png +0 -0
  42. data/doc/guide/src/basics/log_replay/hierarchy_error_3.png +0 -0
  43. data/doc/guide/src/basics/log_replay/plan_repair_1.png +0 -0
  44. data/doc/guide/src/basics/log_replay/plan_repair_2.png +0 -0
  45. data/doc/guide/src/basics/log_replay/plan_repair_3.png +0 -0
  46. data/doc/guide/src/basics/log_replay/plan_repair_4.png +0 -0
  47. data/doc/guide/src/basics/log_replay/roby_log_main_window.png +0 -0
  48. data/doc/guide/src/basics/log_replay/roby_log_relation_window.png +0 -0
  49. data/doc/guide/src/basics/log_replay/roby_replay_event_representation.png +0 -0
  50. data/doc/guide/src/basics/plan_objects.page +71 -0
  51. data/doc/guide/src/basics/relations_display.page +203 -0
  52. data/doc/guide/src/basics/roby_cycle_overview.png +0 -0
  53. data/doc/guide/src/basics/shell.page +102 -0
  54. data/doc/guide/src/basics/summary.page +32 -0
  55. data/doc/guide/src/basics/tasks.page +357 -0
  56. data/doc/guide/src/basics_shell_header.txt +16 -0
  57. data/doc/guide/src/cycle/cycle-overview.png +0 -0
  58. data/doc/guide/src/cycle/cycle-overview.svg +208 -0
  59. data/doc/guide/src/cycle/error_handling.page +168 -0
  60. data/doc/guide/src/cycle/error_instantaneous_repair.png +0 -0
  61. data/doc/guide/src/cycle/error_instantaneous_repair.svg +1224 -0
  62. data/doc/guide/src/cycle/garbage_collection.page +10 -0
  63. data/doc/guide/src/cycle/index.page +23 -0
  64. data/doc/guide/src/cycle/propagation.page +154 -0
  65. data/doc/guide/src/cycle/propagation_diamond.png +0 -0
  66. data/doc/guide/src/cycle/propagation_diamond.svg +1279 -0
  67. data/doc/guide/src/default.css +319 -0
  68. data/doc/guide/src/default.template +74 -0
  69. data/doc/guide/src/htmldoc.metainfo +20 -0
  70. data/doc/guide/src/htmldoc.virtual +18 -0
  71. data/doc/guide/src/images/bodybg.png +0 -0
  72. data/doc/guide/src/images/contbg.png +0 -0
  73. data/doc/guide/src/images/footerbg.png +0 -0
  74. data/doc/guide/src/images/gradient1.png +0 -0
  75. data/doc/guide/src/images/gradient2.png +0 -0
  76. data/doc/guide/src/index.page +7 -0
  77. data/doc/guide/src/introduction/index.page +29 -0
  78. data/doc/guide/src/introduction/install.page +133 -0
  79. data/doc/{papers.rdoc → guide/src/introduction/publications.page} +5 -2
  80. data/doc/{videos.rdoc → guide/src/introduction/videos.page} +4 -2
  81. data/doc/guide/src/plugins/fault_tolerance.page +44 -0
  82. data/doc/guide/src/plugins/index.page +11 -0
  83. data/doc/guide/src/plugins/subsystems.page +45 -0
  84. data/doc/guide/src/relations/dependency.page +89 -0
  85. data/doc/guide/src/relations/index.page +12 -0
  86. data/doc/misc/update_github +24 -0
  87. data/doc/tutorials/02-GoForward.rdoc +3 -3
  88. data/ext/graph/graph.cc +46 -0
  89. data/lib/roby.rb +57 -22
  90. data/lib/roby/app.rb +132 -112
  91. data/lib/roby/app/plugins/rake.rb +21 -0
  92. data/lib/roby/app/rake.rb +0 -7
  93. data/lib/roby/app/run.rb +1 -1
  94. data/lib/roby/app/scripts/distributed.rb +1 -2
  95. data/lib/roby/app/scripts/generate/bookmarks.rb +1 -1
  96. data/lib/roby/app/scripts/results.rb +2 -1
  97. data/lib/roby/app/scripts/run.rb +6 -2
  98. data/lib/roby/app/scripts/shell.rb +11 -11
  99. data/lib/roby/config.rb +1 -1
  100. data/lib/roby/decision_control.rb +62 -3
  101. data/lib/roby/distributed.rb +4 -0
  102. data/lib/roby/distributed/base.rb +8 -0
  103. data/lib/roby/distributed/communication.rb +12 -8
  104. data/lib/roby/distributed/connection_space.rb +61 -44
  105. data/lib/roby/distributed/distributed_object.rb +1 -1
  106. data/lib/roby/distributed/notifications.rb +22 -30
  107. data/lib/roby/distributed/peer.rb +13 -8
  108. data/lib/roby/distributed/proxy.rb +5 -5
  109. data/lib/roby/distributed/subscription.rb +4 -4
  110. data/lib/roby/distributed/transaction.rb +3 -3
  111. data/lib/roby/event.rb +176 -110
  112. data/lib/roby/exceptions.rb +12 -4
  113. data/lib/roby/execution_engine.rb +1604 -0
  114. data/lib/roby/external_process_task.rb +225 -0
  115. data/lib/roby/graph.rb +0 -6
  116. data/lib/roby/interface.rb +221 -137
  117. data/lib/roby/log/console.rb +5 -3
  118. data/lib/roby/log/data_stream.rb +94 -16
  119. data/lib/roby/log/dot.rb +8 -8
  120. data/lib/roby/log/event_stream.rb +13 -3
  121. data/lib/roby/log/file.rb +43 -18
  122. data/lib/roby/log/gui/basic_display_ui.rb +89 -0
  123. data/lib/roby/log/gui/chronicle_view_ui.rb +90 -0
  124. data/lib/roby/log/gui/data_displays.rb +4 -5
  125. data/lib/roby/log/gui/data_displays_ui.rb +146 -0
  126. data/lib/roby/log/gui/relations.rb +18 -18
  127. data/lib/roby/log/gui/relations_ui.rb +120 -0
  128. data/lib/roby/log/gui/relations_view_ui.rb +144 -0
  129. data/lib/roby/log/gui/replay.rb +41 -13
  130. data/lib/roby/log/gui/replay_controls.rb +3 -0
  131. data/lib/roby/log/gui/replay_controls.ui +133 -110
  132. data/lib/roby/log/gui/replay_controls_ui.rb +249 -0
  133. data/lib/roby/log/hooks.rb +19 -18
  134. data/lib/roby/log/logger.rb +7 -6
  135. data/lib/roby/log/notifications.rb +4 -4
  136. data/lib/roby/log/plan_rebuilder.rb +20 -22
  137. data/lib/roby/log/relations.rb +44 -16
  138. data/lib/roby/log/server.rb +1 -4
  139. data/lib/roby/log/timings.rb +88 -19
  140. data/lib/roby/plan-object.rb +135 -11
  141. data/lib/roby/plan.rb +408 -224
  142. data/lib/roby/planning/loops.rb +32 -25
  143. data/lib/roby/planning/model.rb +157 -51
  144. data/lib/roby/planning/task.rb +47 -20
  145. data/lib/roby/query.rb +128 -92
  146. data/lib/roby/relations.rb +254 -136
  147. data/lib/roby/relations/conflicts.rb +6 -9
  148. data/lib/roby/relations/dependency.rb +358 -0
  149. data/lib/roby/relations/ensured.rb +0 -1
  150. data/lib/roby/relations/error_handling.rb +0 -1
  151. data/lib/roby/relations/events.rb +0 -2
  152. data/lib/roby/relations/executed_by.rb +26 -11
  153. data/lib/roby/relations/planned_by.rb +14 -14
  154. data/lib/roby/robot.rb +46 -0
  155. data/lib/roby/schedulers/basic.rb +34 -0
  156. data/lib/roby/standalone.rb +4 -0
  157. data/lib/roby/standard_errors.rb +21 -15
  158. data/lib/roby/state/events.rb +5 -4
  159. data/lib/roby/support.rb +107 -6
  160. data/lib/roby/task-operations.rb +23 -19
  161. data/lib/roby/task.rb +522 -148
  162. data/lib/roby/task_index.rb +80 -0
  163. data/lib/roby/test/common.rb +283 -44
  164. data/lib/roby/test/distributed.rb +53 -37
  165. data/lib/roby/test/testcase.rb +9 -204
  166. data/lib/roby/test/tools.rb +3 -3
  167. data/lib/roby/transactions.rb +154 -111
  168. data/lib/roby/transactions/proxy.rb +40 -7
  169. data/manifest.xml +20 -0
  170. data/plugins/fault_injection/README.txt +0 -3
  171. data/plugins/fault_injection/Rakefile +2 -8
  172. data/plugins/fault_injection/app.rb +1 -1
  173. data/plugins/fault_injection/fault_injection.rb +3 -3
  174. data/plugins/fault_injection/test/test_fault_injection.rb +19 -25
  175. data/plugins/subsystems/README.txt +0 -3
  176. data/plugins/subsystems/Rakefile +2 -7
  177. data/plugins/subsystems/app.rb +27 -16
  178. data/plugins/subsystems/test/app/config/init.rb +3 -0
  179. data/plugins/subsystems/test/app/planners/main.rb +1 -1
  180. data/plugins/subsystems/test/app/tasks/services.rb +1 -1
  181. data/plugins/subsystems/test/test_subsystems.rb +23 -16
  182. data/test/distributed/test_communication.rb +32 -15
  183. data/test/distributed/test_connection.rb +28 -26
  184. data/test/distributed/test_execution.rb +59 -54
  185. data/test/distributed/test_mixed_plan.rb +34 -34
  186. data/test/distributed/test_plan_notifications.rb +26 -26
  187. data/test/distributed/test_protocol.rb +57 -48
  188. data/test/distributed/test_query.rb +11 -7
  189. data/test/distributed/test_remote_plan.rb +71 -71
  190. data/test/distributed/test_transaction.rb +50 -47
  191. data/test/mockups/external_process +28 -0
  192. data/test/planning/test_loops.rb +163 -119
  193. data/test/planning/test_model.rb +3 -3
  194. data/test/planning/test_task.rb +27 -7
  195. data/test/relations/test_conflicts.rb +3 -3
  196. data/test/relations/test_dependency.rb +324 -0
  197. data/test/relations/test_ensured.rb +2 -2
  198. data/test/relations/test_executed_by.rb +94 -19
  199. data/test/relations/test_planned_by.rb +11 -9
  200. data/test/suite_core.rb +6 -3
  201. data/test/suite_distributed.rb +1 -0
  202. data/test/suite_planning.rb +1 -0
  203. data/test/suite_relations.rb +2 -2
  204. data/test/tasks/test_external_process.rb +126 -0
  205. data/test/{test_thread_task.rb → tasks/test_thread_task.rb} +17 -20
  206. data/test/test_bgl.rb +21 -1
  207. data/test/test_event.rb +229 -155
  208. data/test/test_exceptions.rb +79 -80
  209. data/test/test_execution_engine.rb +987 -0
  210. data/test/test_gui.rb +1 -1
  211. data/test/test_interface.rb +11 -5
  212. data/test/test_log.rb +18 -7
  213. data/test/test_log_server.rb +1 -0
  214. data/test/test_plan.rb +229 -395
  215. data/test/test_query.rb +193 -35
  216. data/test/test_relations.rb +88 -8
  217. data/test/test_state.rb +55 -37
  218. data/test/test_support.rb +1 -1
  219. data/test/test_task.rb +371 -218
  220. data/test/test_testcase.rb +32 -16
  221. data/test/test_transactions.rb +211 -170
  222. data/test/test_transactions_proxy.rb +37 -19
  223. metadata +169 -71
  224. data/.gitignore +0 -29
  225. data/doc/styles/allison.css +0 -314
  226. data/doc/styles/allison.js +0 -316
  227. data/doc/styles/allison.rb +0 -276
  228. data/doc/styles/jamis.rb +0 -593
  229. data/lib/roby/control.rb +0 -746
  230. data/lib/roby/executives/simple.rb +0 -30
  231. data/lib/roby/propagation.rb +0 -562
  232. data/lib/roby/relations/hierarchy.rb +0 -239
  233. data/lib/roby/transactions/updates.rb +0 -139
  234. data/test/relations/test_hierarchy.rb +0 -158
  235. data/test/test_control.rb +0 -399
  236. data/test/test_propagation.rb +0 -210
@@ -1,5 +1,3 @@
1
- require 'roby/task'
2
-
3
1
  module Roby::TaskStructure
4
2
  relation :PlannedBy, :child_name => :planning_task,
5
3
  :parent_name => :planned_task, :noinfo => true, :single_child => true do
@@ -21,7 +19,7 @@ module Roby::TaskStructure
21
19
 
22
20
  # Returns a set of PlanningFailedError exceptions for all abstract tasks
23
21
  # for which planning has failed
24
- def PlannedBy.check_planning(plan)
22
+ def PlannedBy.check_structure(plan)
25
23
  result = []
26
24
  Roby::TaskStructure::PlannedBy.each_edge do |planned_task, planning_task, _|
27
25
  next unless plan == planning_task.plan && planning_task.failed?
@@ -43,21 +41,23 @@ module Roby
43
41
 
44
42
  def initialize(planned_task, planning_task)
45
43
  @planned_task = planned_task
46
- super(planning_task.terminal_event)
44
+ super(planning_task.failure_event)
47
45
  end
46
+ def pretty_print(pp)
47
+ pp.text "failed to plan "
48
+ planned_task.pretty_print(pp)
49
+ pp.breakable
50
+ pp.breakable
51
+ pp.text "the following planning task failed with the #{failure_point.symbol} event"
52
+ pp.breakable
53
+ failed_task.pretty_print(pp)
54
+ pp.breakable
48
55
 
49
- def message # :nodoc:
50
- msg = "failed to plan #{planned_task}.planned_by(#{failed_task}): failed with #{failure_point.symbol}"
51
56
  if failure_point.context
52
- if failure_point.context.first.respond_to?(:full_message)
53
- msg << "\n" << failure_point.context.first.full_message
54
- else
55
- msg << "(" << failure_point.context.first.to_s << ")"
56
- end
57
+ pp.breakable
58
+ failure_point.context.first.pretty_print(pp)
57
59
  end
58
- msg
59
- end
60
+ end
60
61
  end
61
- Control.structure_checks << TaskStructure::PlannedBy.method(:check_planning)
62
62
  end
63
63
 
@@ -3,5 +3,51 @@ module Robot
3
3
  attr_accessor :logger
4
4
  end
5
5
  extend Logger::Forward
6
+
7
+ def self.prepare_action(name, arguments)
8
+ # Check if +name+ is a planner method, and in that case
9
+ # add a planning method for it and plan it
10
+ planner_model = Roby.app.planners.find do |planner_model|
11
+ planner_model.has_method?(name)
12
+ end
13
+ if !planner_model
14
+ raise ArgumentError, "no such planning method #{name}"
15
+ end
16
+
17
+ m = planner_model.model_of(name, arguments)
18
+
19
+ # HACK: m.returns should not be nil, but it sometimes happen
20
+ returns_model = (m.returns if m && m.returns) || Task
21
+
22
+ if returns_model.kind_of?(Roby::TaskModelTag)
23
+ task = Roby::Task.new
24
+ task.extend returns_model
25
+ else
26
+ # Create an abstract task which will be planned
27
+ task = returns_model.new
28
+ end
29
+
30
+ planner = Roby::PlanningTask.new(:planner_model => planner_model, :method_name => name, :method_options => arguments)
31
+ task.planned_by planner
32
+ return task, planner
33
+ end
34
+
35
+ def self.method_missing(name, *args)
36
+ if name.to_s =~ /!$/
37
+ name = $`.to_sym
38
+ else
39
+ super
40
+ end
41
+
42
+ if args.size > 1
43
+ raise ArgumentError, "wrong number of arguments (#{args.size} for 1) in #{name}!"
44
+ end
45
+
46
+ options = args.first || {}
47
+ task, planner = Robot.prepare_action(name, options)
48
+ Roby.plan.add_mission(task)
49
+
50
+ return task, planner
51
+ end
6
52
  end
7
53
 
@@ -0,0 +1,34 @@
1
+ module Roby
2
+ module Schedulers
3
+ class Basic
4
+ attr_reader :query
5
+ attr_reader :include_children
6
+ def initialize(include_children = false)
7
+ @include_children = include_children
8
+ @query = Roby.plan.find_tasks.
9
+ executable.
10
+ pending.
11
+ self_owned
12
+ end
13
+ def initial_events
14
+ for task in query.reset
15
+ if !(task.event(:start).root? && task.event(:start).controlable?)
16
+ next
17
+ end
18
+
19
+ root_task =
20
+ if task.root?(TaskStructure::Dependency)
21
+ true
22
+ else
23
+ task.planned_tasks.all? { |t| !t.executable? }
24
+ end
25
+
26
+ if root_task || (include_children && task.parents.any? { |t| t.running? })
27
+ task.start!
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+
@@ -0,0 +1,4 @@
1
+ require 'roby'
2
+ Dir.chdir(APP_DIR)
3
+ Roby.app.setup_global_singletons
4
+
@@ -1,4 +1,3 @@
1
- require 'pp'
2
1
  module Roby
3
2
  # This kind of errors are generated during the plan execution, allowing to
4
3
  # blame a fault on a plan object (#failure_point). The precise failure
@@ -76,6 +75,11 @@ module Roby
76
75
  # Raised when a consistency check failed in the Roby propagation code
77
76
  class PropagationError < InternalError; end
78
77
 
78
+ # Some operations need to be performed in the control thread, and some
79
+ # other (namely blocking operations) must not. This exception is raised
80
+ # when this constraint is not met.
81
+ class PhaseMismatch < RuntimeError; end
82
+
79
83
  # Some operations need to be performed in the control thread, and some
80
84
  # other (namely blocking operations) must not. This exception is raised
81
85
  # when this constraint is not met.
@@ -136,21 +140,25 @@ module Roby
136
140
  # Raised when an event has become unreachable while other parts of the plan
137
141
  # where waiting for its emission.
138
142
  class UnreachableEvent < LocalizedError
139
- # The generator which has become unreachable
140
- attr_reader :generator
143
+ # Why did the generator become unreachable
144
+ attr_reader :reason
145
+
141
146
  # Create an UnreachableEvent error for the given +generator+. +reason+
142
147
  # is supposed to be either nil or a plan object which is the reason why
143
148
  # +generator+ has become unreachable.
144
149
  def initialize(generator, reason)
145
- @generator = generator
146
- super(reason || generator)
150
+ @reason = reason
151
+ super(generator)
147
152
  end
148
153
 
149
154
  def pretty_print(pp) # :nodoc:
150
- pp.text "#{generator} has become unreachable"
151
- if failure_point
152
- pp.breakable ':'
153
- failure_point.pretty_print(pp)
155
+ pp.text "#{failed_generator} has become unreachable"
156
+ if reason
157
+ reason = [*reason]
158
+ reason.each do |e|
159
+ pp.breakable
160
+ e.pretty_print(pp)
161
+ end
154
162
  end
155
163
  end
156
164
  end
@@ -180,12 +188,10 @@ module Roby
180
188
  attr_reader :from
181
189
  # The task which should have replaced #from
182
190
  attr_reader :to
183
- # A description of the replacement failure
184
- attr_reader :error
185
191
 
186
192
  # Create a new InvalidReplace object
187
- def initialize(from, to, error)
188
- @from, @to, @error = from, to, error
193
+ def initialize(from, to)
194
+ @from, @to = from, to
189
195
  end
190
196
  def pretty_print(pp) # :nodoc:
191
197
  pp.text "invalid replacement: #{message}"
@@ -202,7 +208,7 @@ module Roby
202
208
  class MissionFailedError < LocalizedError
203
209
  # Create a new MissionFailedError for the given mission
204
210
  def initialize(task)
205
- super(task.terminal_event)
211
+ super(task.failure_event || task)
206
212
  end
207
213
 
208
214
  def pretty_print(pp)
@@ -213,6 +219,6 @@ module Roby
213
219
 
214
220
  # Exception raised in threads which are waiting for the control thread
215
221
  # See for instance Roby.execute
216
- class ControlQuitError < RuntimeError; end
222
+ class ExecutionQuitError < RuntimeError; end
217
223
  end
218
224
 
@@ -61,15 +61,16 @@ module Roby
61
61
  end
62
62
  end
63
63
 
64
- # Registered on Control to call the #poll method of state events
65
- def self.poll_state_events # :nodoc:
66
- for ev in Roby.plan.free_events
64
+ # Registered on the execution engines to call the #poll method of state
65
+ # events
66
+ def self.poll_state_events(plan) # :nodoc:
67
+ for ev in plan.free_events
67
68
  if ev.kind_of?(StateEvent) && ev.enabled?
68
69
  ev.poll
69
70
  end
70
71
  end
71
72
  end
72
- Roby::Control.each_cycle(&Roby.method(:poll_state_events))
73
+ Roby::ExecutionEngine.propagation_handlers << Roby.method(:poll_state_events)
73
74
 
74
75
  # A state event is an event which emits when some parameters over the state
75
76
  # are reached. See DeltaEvent and TimePointEvent.
@@ -1,9 +1,6 @@
1
- require 'active_support/inflector'
2
- class String # :nodoc: all
3
- include ActiveSupport::CoreExtensions::String::Inflections
4
- end
5
-
6
1
  require 'roby/config'
2
+ require 'facets/string/camelcase'
3
+ require 'facets/string/snakecase'
7
4
  require 'facets/kernel/constant'
8
5
  require 'utilrb/enumerable'
9
6
  require 'utilrb/time/to_hms'
@@ -45,11 +42,11 @@ module Enumerable
45
42
  end
46
43
 
47
44
  class Module
48
- # Defines a new constant under a given module
49
45
  # :call-seq
50
46
  # define_under(name, value) -> value
51
47
  # define_under(name) { ... } -> value
52
48
  #
49
+ # Defines a new constant under a given module
53
50
  # In the first form, the method gets its value from its argument.
54
51
  # In the second case, it calls the provided block
55
52
  def define_under(name, value = nil)
@@ -88,5 +85,109 @@ module Roby
88
85
 
89
86
  extend Logger::Hierarchy
90
87
  extend Logger::Forward
88
+
89
+ class Pool < Queue
90
+ def initialize(klass)
91
+ @klass = klass
92
+ super()
93
+ end
94
+
95
+ def pop
96
+ value = super(true) rescue nil
97
+ value || @klass.new
98
+ end
99
+ end
100
+
101
+ @mutexes = Pool.new(Mutex)
102
+ @condition_variables = Pool.new(ConditionVariable)
103
+ class << self
104
+ # A pool of mutexes (as a Queue)
105
+ attr_reader :mutexes
106
+ # A pool of condition variables (as a Queue)
107
+ attr_reader :condition_variables
108
+ end
109
+
110
+ # call-seq:
111
+ # condition_variable => cv
112
+ # condition_variable(true) => cv, mutex
113
+ # condition_variable { |cv| ... } => value returned by the block
114
+ # condition_variable(true) { |cv, mutex| ... } => value returned by the block
115
+ #
116
+ # Get a condition variable object from the Roby.condition_variables
117
+ # pool and, if mutex is not true, a Mutex object
118
+ #
119
+ # If a block is given, the two objects are yield and returned into the
120
+ # pool after the block has returned. In that case, the method returns
121
+ # the value returned by the block
122
+ def self.condition_variable(mutex = false)
123
+ cv = condition_variables.pop
124
+
125
+ if block_given?
126
+ begin
127
+ if mutex
128
+ mt = mutexes.pop
129
+ yield(cv, mt)
130
+ else
131
+ yield(cv)
132
+ end
133
+
134
+ ensure
135
+ return_condition_variable(cv, mt)
136
+ end
137
+ else
138
+ if mutex
139
+ return cv, mutexes.pop
140
+ else
141
+ return cv
142
+ end
143
+ end
144
+ end
145
+
146
+ # Returns a ConditionVariable and optionally a Mutex into the
147
+ # Roby.condition_variables and Roby.mutexes pools
148
+ def self.return_condition_variable(cv, mutex = nil)
149
+ condition_variables.push cv
150
+ if mutex
151
+ mutexes.push mutex
152
+ end
153
+ nil
154
+ end
155
+
156
+ @global_lock = Mutex.new
157
+ class << self
158
+ # This Mutex object is locked during the event propagation loop, and
159
+ # unlock while this loop is sleeping. It is used to wait for the
160
+ # availability of the main plan.
161
+ attr_reader :global_lock
162
+ end
163
+
164
+ def self.taken_global_lock?; Thread.current[:global_lock_taken] end
165
+
166
+ # Implements a recursive behaviour on Roby.mutex
167
+ def self.synchronize
168
+ if Thread.current[:global_lock_taken]
169
+ yield
170
+ else
171
+ global_lock.lock
172
+ begin
173
+ Thread.current[:global_lock_taken] = true
174
+ yield
175
+ ensure
176
+ Thread.current[:global_lock_taken] = false
177
+ global_lock.unlock
178
+ end
179
+ end
180
+ end
181
+
182
+ class << self
183
+ attr_accessor :enable_deprecation_warnings
184
+ end
185
+ @enable_deprecation_warnings = true
186
+
187
+ def self.warn_deprecated(msg)
188
+ if enable_deprecation_warnings
189
+ Roby.warn "Deprecation Warning: #{msg} at #{caller[1]}"
190
+ end
191
+ end
91
192
  end
92
193
 
@@ -1,5 +1,3 @@
1
- require 'roby/task'
2
-
3
1
  module Roby
4
2
  module TaskOperations
5
3
  def +(task)
@@ -60,31 +58,34 @@ module Roby
60
58
  def to_task(task = nil)
61
59
  return super() unless task
62
60
  task = task.new unless task.kind_of?(Roby::Task)
63
- @tasks.each { |t| task.realized_by t }
61
+ @tasks.each { |t| task.depends_on t }
64
62
 
65
- task.on(:start, @tasks.first, :start)
66
- @tasks.last.forward(:success, task, :success)
63
+ task.signals(:start, @tasks.first, :start)
64
+ @tasks.last.forward_to(:success, task, :success)
67
65
 
68
66
  delete
69
67
 
70
68
  task
71
69
  end
70
+ def child_of(task = nil)
71
+ to_task(task)
72
+ end
72
73
 
73
74
  def connect_start(task)
74
75
  if old = @tasks.first
75
76
  event(:start).remove_signal old.event(:start)
76
- task.on(:success, old, :start)
77
+ task.signals(:success, old, :start)
77
78
  end
78
79
 
79
- event(:start).on task.event(:start)
80
+ event(:start).signals task.event(:start)
80
81
  end
81
82
 
82
83
  def connect_stop(task)
83
84
  if old = @tasks.last
84
- old.on(:success, task, :start)
85
+ old.signals(:success, task, :start)
85
86
  old.event(:success).remove_forwarding event(:success)
86
87
  end
87
- task.forward(:success, self)
88
+ task.forward_to(:success, self, :success)
88
89
  end
89
90
  private :connect_stop, :connect_start
90
91
 
@@ -94,7 +95,7 @@ module Roby
94
95
  connect_stop(task) if @tasks.empty?
95
96
 
96
97
  @tasks.unshift(task)
97
- realized_by task
98
+ depends_on task
98
99
  self
99
100
  end
100
101
 
@@ -104,7 +105,7 @@ module Roby
104
105
  connect_stop(task)
105
106
 
106
107
  @tasks << task
107
- realized_by task
108
+ depends_on task
108
109
  self
109
110
  end
110
111
 
@@ -121,16 +122,19 @@ module Roby
121
122
  super
122
123
 
123
124
  @children_success = Roby::AndGenerator.new
124
- @children_success.forward event(:success)
125
+ @children_success.forward_to event(:success)
125
126
  end
126
127
 
128
+ def child_of(task = nil)
129
+ to_task(task)
130
+ end
127
131
  def to_task(task = nil)
128
132
  return super() unless task
129
133
 
130
134
  task = task.new unless task.kind_of?(Roby::Task)
131
135
  @tasks.each do |t|
132
- task.realized_by t
133
- task.on(:start, t, :start)
136
+ task.depends_on t
137
+ task.signals(:start, t, :start)
134
138
  end
135
139
  task.event(:success).emit_on children_success
136
140
 
@@ -143,8 +147,8 @@ module Roby
143
147
  raise "trying to change a running parallel task" if running?
144
148
  @tasks << task
145
149
 
146
- on(:start, task, :start)
147
- realized_by task
150
+ signals(:start, task, :start)
151
+ depends_on task
148
152
  children_success << task.event(:success)
149
153
 
150
154
  self
@@ -162,10 +166,10 @@ module Roby
162
166
 
163
167
  success = AndGenerator.new
164
168
  tasks.each do |task|
165
- realized_by task
166
- task.event(:success).on success
169
+ depends_on task
170
+ task.event(:success).signals success
167
171
  end
168
- success.forward event(:success)
172
+ success.forward_to event(:success)
169
173
  end
170
174
 
171
175
  event :start do