rachinations 0.0.1

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 (91) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +6 -0
  4. data/.travis.yml +8 -0
  5. data/.yardopts +1 -0
  6. data/Gemfile +19 -0
  7. data/Gemfile.lock +93 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +18 -0
  10. data/Rakefile +16 -0
  11. data/lib/rachinations.rb +49 -0
  12. data/lib/rachinations/domain/diagrams/diagram.rb +167 -0
  13. data/lib/rachinations/domain/diagrams/non_deterministic_diagram.rb +16 -0
  14. data/lib/rachinations/domain/diagrams/verbose_diagram.rb +9 -0
  15. data/lib/rachinations/domain/edge_collection.rb +12 -0
  16. data/lib/rachinations/domain/edges/edge.rb +159 -0
  17. data/lib/rachinations/domain/edges/random_edge.rb +4 -0
  18. data/lib/rachinations/domain/exceptions/bad_options.rb +3 -0
  19. data/lib/rachinations/domain/exceptions/no_elements_found.rb +2 -0
  20. data/lib/rachinations/domain/exceptions/no_elements_matching_condition_error.rb +2 -0
  21. data/lib/rachinations/domain/exceptions/no_elements_of_given_type.rb +3 -0
  22. data/lib/rachinations/domain/exceptions/unsupported_type_error.rb +2 -0
  23. data/lib/rachinations/domain/modules/common/hash_init.rb +88 -0
  24. data/lib/rachinations/domain/modules/common/invariant.rb +17 -0
  25. data/lib/rachinations/domain/modules/diagrams/verbose.rb +30 -0
  26. data/lib/rachinations/domain/node_collection.rb +30 -0
  27. data/lib/rachinations/domain/nodes/converter.rb +276 -0
  28. data/lib/rachinations/domain/nodes/gate.rb +6 -0
  29. data/lib/rachinations/domain/nodes/node.rb +166 -0
  30. data/lib/rachinations/domain/nodes/pool.rb +267 -0
  31. data/lib/rachinations/domain/nodes/resourceful_node.rb +96 -0
  32. data/lib/rachinations/domain/nodes/resourceless_node.rb +11 -0
  33. data/lib/rachinations/domain/nodes/sink.rb +17 -0
  34. data/lib/rachinations/domain/nodes/source.rb +161 -0
  35. data/lib/rachinations/domain/nodes/trader.rb +6 -0
  36. data/lib/rachinations/domain/resource_bag.rb +131 -0
  37. data/lib/rachinations/domain/resources/token.rb +51 -0
  38. data/lib/rachinations/domain/strategies/strategy.rb +5 -0
  39. data/lib/rachinations/domain/strategies/valid_types.rb +69 -0
  40. data/lib/rachinations/dsl/dsl.rb +63 -0
  41. data/lib/rachinations/extras/fifo.rb +27 -0
  42. data/lib/rachinations/version.rb +3 -0
  43. data/machinations_diagrams/apenas_bonito.xml +22 -0
  44. data/machinations_diagrams/behavior_converter.xml +53 -0
  45. data/machinations_diagrams/behavior_converter_fim.xml +10 -0
  46. data/machinations_diagrams/canon/README.md +8 -0
  47. data/machinations_diagrams/canon/converters_differences.xml +27 -0
  48. data/machinations_diagrams/canon/converters_differences2.xml +34 -0
  49. data/machinations_diagrams/canon/converters_similarities.xml +63 -0
  50. data/machinations_diagrams/canon/converters_similarities2.xml +21 -0
  51. data/machinations_diagrams/canon/nodes_and_edges_differences.xml +15 -0
  52. data/machinations_diagrams/canon/nodes_and_edges_similarities.xml +20 -0
  53. data/machinations_diagrams/deterministic_example.xml +46 -0
  54. data/machinations_diagrams/economies_of_scale.xml +32 -0
  55. data/machinations_diagrams/feature_ou_bug.xml +5 -0
  56. data/machinations_diagrams/loop_in_trigger.xml +21 -0
  57. data/machinations_diagrams/naficadevendo.xml +12 -0
  58. data/machinations_diagrams/noreporting_equivalent.xml +22 -0
  59. data/machinations_diagrams/pull_all_example.xml +7 -0
  60. data/machinations_diagrams/sketch_of_memory.xml +41 -0
  61. data/machinations_diagrams/software_engineering_process 2.xml +130 -0
  62. data/machinations_diagrams/software_engineering_process v3.xml +168 -0
  63. data/machinations_diagrams/software_engineering_process v4.xml +192 -0
  64. data/machinations_diagrams/software_engineering_process.xml +65 -0
  65. data/machinations_diagrams/software_engineering_process_with_rework_after_test.xml +195 -0
  66. data/machinations_diagrams/startup_marketing.xml +35 -0
  67. data/machinations_diagrams/triggers_allow_multiple_stages_at_same_round.xml +19 -0
  68. data/machinations_diagrams/um_de_cada_vez_vs_todos_de_uma_vez.xml +20 -0
  69. data/rachinations.gemspec +35 -0
  70. data/testing/features/step_definitions/step_definitions.rb +11 -0
  71. data/testing/simulations/modelo1.rb +20 -0
  72. data/testing/simulations/modelo2.rb +49 -0
  73. data/testing/simulations/noreporting.rb +51 -0
  74. data/testing/simulations/sequencial.rb +19 -0
  75. data/testing/simulations/sobonito.rb +28 -0
  76. data/testing/simulations/sobonitowhile.rb +28 -0
  77. data/testing/simulations/whatIwish1.rb +20 -0
  78. data/testing/spec/canon/converter_spec.rb +33 -0
  79. data/testing/spec/canon/pool_spec.rb +68 -0
  80. data/testing/spec/conditions_spec.rb +10 -0
  81. data/testing/spec/converter_spec.rb +223 -0
  82. data/testing/spec/diagram_spec.rb +671 -0
  83. data/testing/spec/edge_spec.rb +256 -0
  84. data/testing/spec/hash_init_spec.rb +59 -0
  85. data/testing/spec/node_spec.rb +31 -0
  86. data/testing/spec/non_deterministic_diagram_spec.rb +112 -0
  87. data/testing/spec/pool_spec.rb +233 -0
  88. data/testing/spec/source_spec.rb +132 -0
  89. data/testing/spec/spec_helper.rb +34 -0
  90. data/testing/spec/xexeo_spec.rb +193 -0
  91. metadata +283 -0
@@ -0,0 +1,12 @@
1
+ require 'forwardable'
2
+
3
+ class EdgeCollection
4
+ extend Forwardable
5
+
6
+ def_delegators :@edges, :[], :<<, :each, :push, :map, :select, :detect, :reduce
7
+
8
+ def initialize
9
+ @edges = []
10
+ end
11
+
12
+ end
@@ -0,0 +1,159 @@
1
+ require_relative '../strategies/valid_types'
2
+ require_relative '../../domain/exceptions/no_elements_found'
3
+
4
+ class Edge
5
+
6
+ attr_reader :from, :to, :name, :label, :types
7
+
8
+
9
+ def initialize(hsh)
10
+
11
+ @name = hsh.fetch(:name)
12
+
13
+ @from = hsh.fetch(:from)
14
+
15
+ @to = hsh.fetch(:to)
16
+
17
+ #setting default values if needed.
18
+ hsh = defaults.merge hsh
19
+
20
+ @label = hsh.fetch(:label)
21
+ @types = hsh.fetch(:types)
22
+
23
+ end
24
+
25
+ # Simulates a ping!, but no resources get actually
26
+ # moved.
27
+ #
28
+ # @param [Boolean] require_all whether to require that the maximum
29
+ # number of Resources allowed (as per this Edge's label) be
30
+ # able to pass in order to return true.
31
+ #
32
+ # @return [Boolean] true in case a ping! on this Edge
33
+ # would return true. False otherwise.
34
+ def test_ping?(require_all=false)
35
+ return false if from.disabled? || to.disabled?
36
+
37
+ condition = strategy.condition
38
+
39
+ available_resources = from.resource_count(&condition)
40
+
41
+ if available_resources == 0
42
+ false
43
+ elsif available_resources >= label
44
+ true
45
+ elsif available_resources < label && require_all
46
+ false
47
+ else
48
+ # only some resources are able to pass but it's not require_all
49
+ true
50
+ end
51
+
52
+ end
53
+
54
+ # the code is the code but sometimes it helps to specify what action
55
+ # we are talking about so as to make code more understandable
56
+ alias_method :test_pull?, :test_ping?
57
+ alias_method :test_push?, :test_ping?
58
+
59
+ def supports?(type)
60
+ types.empty? || types.include?(type)
61
+ end
62
+
63
+ alias_method :support?, :supports?
64
+
65
+ def enabled?
66
+ true
67
+ end
68
+
69
+ def disabled?
70
+ not enabled?
71
+ end
72
+
73
+ def untyped?
74
+ types.empty?
75
+ end
76
+
77
+ def typed?
78
+ not untyped?
79
+ end
80
+
81
+ def from?(obj)
82
+ from.equal?(obj)
83
+ end
84
+
85
+ def to?(obj)
86
+ to.equal?(obj)
87
+ end
88
+
89
+ # Returns a block which will be later used by the calling node to search
90
+ # for a suitable resource.
91
+ #
92
+ # @return [Proc] a condition block
93
+ def push_expression
94
+ strategy.push_condition
95
+ end
96
+
97
+ # Returns a block which will be later used as a parameter
98
+ # to method pull!.
99
+ #
100
+ # @return [Proc] a condition block
101
+ def pull_expression
102
+ strategy.pull_condition
103
+ end
104
+
105
+ # Takes a resource and puts it into the node at the other
106
+ # end of this Edge.
107
+ #
108
+ # @raise [RuntimeError] in case the receiving node or this Edge
109
+ # won't accept the resource sent.
110
+ # @param res the resource to send.
111
+ def push!(res)
112
+ raise RuntimeError.new "This Edge does not support type: #{res.type}" unless supports?(res.type)
113
+
114
+ begin
115
+ to.put_resource!(res,self)
116
+ rescue => e
117
+ # just to make it clear that it bubbles
118
+ raise RuntimeError.new(e.message+" => "+'Push failed')
119
+ end
120
+ end
121
+
122
+ # Tries to take a resource matching given block
123
+ # from the node at the other end.
124
+ #
125
+ # @param [Proc] blk block that will define what resource the other node
126
+ # should send.
127
+ # @raise [RuntimeError] in case the other node could provide no resources
128
+ # that satisfy this condition block.
129
+ # @return a resource that satisfies the given block.
130
+ def pull!(&blk)
131
+ begin
132
+ res=from.take_resource!(&blk)
133
+ rescue => e
134
+ # just to make it clear that it bubbles
135
+ raise RuntimeError.new("Pull failed")
136
+ else
137
+ res
138
+ end
139
+
140
+ end
141
+
142
+ def to_s
143
+ "Edge '#{@name}', from '#{from.name}' to '#{to.name}'"
144
+ end
145
+
146
+ private
147
+
148
+ def strategy
149
+ ValidTypes.new(from, self, to)
150
+ end
151
+
152
+ def defaults
153
+ {
154
+ :label => 1,
155
+ :types => []
156
+ }
157
+ end
158
+
159
+ end
@@ -0,0 +1,4 @@
1
+ require_relative '../../domain/edges/edge'
2
+
3
+ class RandomEdge < Edge
4
+ end
@@ -0,0 +1,3 @@
1
+ class BadOptions < ArgumentError
2
+
3
+ end
@@ -0,0 +1,2 @@
1
+ class NoElementsFound < RuntimeError
2
+ end
@@ -0,0 +1,2 @@
1
+ class NoElementsMatchingConditionError < RuntimeError
2
+ end
@@ -0,0 +1,3 @@
1
+ class NoElementsOfGivenTypeError < RuntimeError
2
+
3
+ end
@@ -0,0 +1,2 @@
1
+ class UnsupportedTypeError < RuntimeError
2
+ end
@@ -0,0 +1,88 @@
1
+ #use this for classes you want to be able to instantiate
2
+ #using a hashful of parameters
3
+ module HashInit
4
+
5
+ class ::Array
6
+
7
+ def include_option? opt
8
+
9
+ each do |el|
10
+ if el == opt
11
+ return true
12
+ elsif el.is_a?(Hash) && el.has_key?(opt)
13
+ return true
14
+ end
15
+ end
16
+
17
+ false
18
+ end
19
+
20
+ end
21
+
22
+ def initialize(hsh={})
23
+
24
+ raise BadOptions.new 'This class requires a hash as parameter to its constructor.' if !hsh.is_a?(Hash)
25
+
26
+ check_options!(hsh)
27
+ hsh=set_defaults(hsh)
28
+ end
29
+
30
+ def check_options!(hsh)
31
+
32
+ #watch out for unknown options - might be typos!
33
+ hsh.each_pair do |key, value|
34
+
35
+ if !options.include_option?(key) && aliases_for(key).none?{|ali| options.include_option?(ali) }
36
+ raise BadOptions.new "Unknown option in parameter hash: :#{key} "
37
+ end
38
+ end
39
+
40
+ #make sure all required ones are there
41
+
42
+ options.each do |el|
43
+ if el.is_a? Hash
44
+
45
+ #we know for sure it's got only one key and one value
46
+ k = el.keys[0]
47
+ v = el.values[0]
48
+
49
+ if v == :required
50
+
51
+ if !hsh.has_key?(k) && hsh.keys.all?{|opt| aliases_for(opt).none?{|ali| ali == k } }
52
+ raise BadOptions.new "Required option #{k} was not found in parameter hash."
53
+ end
54
+ end
55
+
56
+ end
57
+ end
58
+
59
+ end
60
+
61
+ def aliases_for(opt)
62
+ aliases.select{|k,v| k == opt }.values
63
+ end
64
+
65
+ def set_defaults(hsh)
66
+ #in case the user hasn't passed full parameters to the constructor
67
+ defaults.merge hsh
68
+ end
69
+
70
+ # This method should be implemented by each client to indicate the options accepted.
71
+ #@return [Array] An array of accepted options.
72
+ #@example Many client Classes specify a :name option:
73
+ # def options
74
+ # [:name]
75
+ # end
76
+ def options
77
+ []
78
+ end
79
+
80
+ def defaults
81
+ {}
82
+ end
83
+
84
+ def aliases
85
+ {}
86
+ end
87
+
88
+ end
@@ -0,0 +1,17 @@
1
+ module Invariant
2
+
3
+ #used to insert assertions into code
4
+ #remember that assertions should not be used to control program flow!!! assert things that should ALWAYS be false.
5
+
6
+ class AssertionError < RuntimeError
7
+
8
+ end
9
+
10
+
11
+
12
+ def invariant &block
13
+ raise AssertionError unless yield
14
+ end
15
+
16
+ alias_method :inv, :invariant
17
+ end
@@ -0,0 +1,30 @@
1
+ module Verbose
2
+
3
+
4
+ def before_run
5
+ print "\033[1;32m===== INITIAL STATE =====\e[00m\n\n"
6
+
7
+ puts self
8
+ end
9
+
10
+ def after_run
11
+ print "\033[1;32m====== FINAL STATE ======\e[00m\n\n"
12
+
13
+ puts self
14
+
15
+ print "\033[1;31m========== END ==========\e[00m\n\n"
16
+ end
17
+
18
+ def before_round(round_no)
19
+ print "======= ROUND #{round_no} =======\n\n"
20
+ end
21
+
22
+ def after_round (round_no)
23
+ puts self
24
+ end
25
+
26
+ def sanity_check_message
27
+ print "\033[1;31m= SAFEGUARD CONDITION REACHED - ABORTING EXECUTION =\e[00m\n\n"
28
+ end
29
+
30
+ end
@@ -0,0 +1,30 @@
1
+ require 'forwardable'
2
+
3
+ class NodeCollection
4
+ extend Forwardable
5
+
6
+ def_delegators :@array, :[], :<<, :each, :push, :map, :select, :detect , :reduce, :shuffle, :sample
7
+
8
+
9
+ def initialize(init_array=nil)
10
+
11
+ if init_array.nil?
12
+ @array = []
13
+ else
14
+ @array = init_array
15
+ end
16
+ end
17
+
18
+ def passive
19
+ @array.select{|el| el.passive? }
20
+ end
21
+
22
+ def automatic
23
+ @array.select{|el| el.automatic? }
24
+ end
25
+
26
+ def detect_by_name(name)
27
+ @array.detect{|el| el.name === name }
28
+ end
29
+
30
+ end
@@ -0,0 +1,276 @@
1
+ require_relative '../../domain/nodes/node'
2
+ require_relative '../../domain/nodes/resourceless_node'
3
+
4
+ class Converter < ResourcefulNode
5
+
6
+ # VEJA O DIAGRAMA BEHAVIOR CONVERTER, inclusive com o equivalente dele
7
+
8
+ # um converter, ao ser ativado, deve tirar de um lugar e passar para outro
9
+ # nada fica guardado em um converter no sentido do pool, porém algumas coisas podem ficar
10
+ # temporariamente anotadas nele porque não foi completado ainda o & ou todos os recursos necessários
11
+
12
+ # um converter pode ser ativado de 3 maneiras
13
+ # por si mesmo
14
+ # quando um no que empurra empurra algo para ele
15
+ # quando um no que puxa puxa dele
16
+
17
+ # O tipo do conversor define o tipo de saida padrao
18
+ # porem o tipo do edge tem vantagem na definicao da saida
19
+ # O exemplo com 3 saidas mostra isso
20
+
21
+ def initialize(hsh={})
22
+ check_options!(hsh)
23
+ hsh = set_defaults(hsh)
24
+ @name = hsh.fetch(:name)
25
+ @mode = hsh.fetch(:mode)
26
+ @types = hsh.fetch(:types)
27
+ @activation = hsh.fetch(:activation)
28
+
29
+ # each edge may have contributed with some resources at any given time
30
+ @resources_contributed = init_resources
31
+
32
+ end
33
+
34
+ # Activates this Converter. It will try to pull from
35
+ # incoming nodes and, if successful, will push into
36
+ # outgoing nodes.
37
+ def trigger!
38
+
39
+ if all?
40
+
41
+ if incoming_edges.all? { |edge| edge.test_pull?(true) } && outgoing_edges.all? { |edge| edge.test_push?(true) }
42
+ pull_all!
43
+ push_all!
44
+ else
45
+ # does not trigger
46
+ end
47
+
48
+ elsif any?
49
+
50
+ pull_any!
51
+
52
+ if in_conditions_met?
53
+ if outgoing_edges.all? { |edge| edge.test_push?(true) }
54
+ push_all!
55
+ pop_stored_resources!
56
+ end # converters are always push_all
57
+ end # conditions weren't met this turn
58
+
59
+ else
60
+ raise ArgumentError.new "Unsupported mode :#{mode}"
61
+ end
62
+
63
+ end
64
+
65
+ # Puts a Resource into a Converter. The Edge may be used
66
+ # as index for internal states and the Resource may be
67
+ # used in case not all edge conditions have been met
68
+ # (only applicable when in pull_any mode).
69
+ #
70
+ def put_resource!(res, edge=nil)
71
+ inv { !edge.nil? }
72
+ if all?
73
+ if incoming_edges.all? { |e| e.test_push? }
74
+ push_all!
75
+ end
76
+ elsif any?
77
+ add_to_contributed_resources!(res, edge)
78
+ if in_conditions_met?
79
+ push_all!
80
+ end
81
+ end
82
+
83
+ end
84
+
85
+ # An override for the original method. The reason for this is
86
+ # that, when an Edge is attached to a Converter after it's been
87
+ # created, a key for it (frozen) needs to be created.
88
+ #
89
+ # @param [Edge] edge
90
+ def attach_edge!(edge)
91
+ #TODO use argument (edge) on the call to super and make sure tests still pass
92
+ # that way it's clearer that it is being passed on to super
93
+ super
94
+ resources_contributed.store(edge, Fifo.new)
95
+ self
96
+ end
97
+
98
+ def take_resource!(type=nil, &blk)
99
+ if incoming_edges.shuffle.all? { |edge| edge.test_pull? }
100
+ pull_all!
101
+ end
102
+ end
103
+
104
+
105
+ def resource_count(type=nil,&block)
106
+ return Float::INFINITY
107
+ end
108
+
109
+ def to_s
110
+ "Converter '#{@name}'"
111
+ end
112
+
113
+ private
114
+
115
+ # This method is used to test whether a Converter
116
+ # has had the conditions for incoming edges met.
117
+ #
118
+ # @return [Boolean] true if conditions for pull_any
119
+ # have all been met, false otherwise
120
+ def in_conditions_met?
121
+
122
+ edges = incoming_edges
123
+
124
+ incoming_edges
125
+ .all? { |edge| resources_contributed.keys.include?(edge) && resources_contributed.fetch(edge).length >= edge.label }
126
+ end
127
+
128
+ # This removes from the internal store just enough
129
+ # resources to accomplish one push_all (only applicable when in pull_any mode)
130
+ def pop_stored_resources!
131
+ #TODO
132
+ end
133
+
134
+
135
+ attr_accessor :resources_contributed
136
+
137
+ def pull_any!
138
+ incoming_edges
139
+ .shuffle
140
+ .each do |edge|
141
+ begin
142
+ blk = edge.pull_expression
143
+ rescue RuntimeError => ex
144
+ # Could not get a block for one Edge, but this is pull_any so I'll go ahead.
145
+ next #other edges might still be able to serve me.
146
+ end
147
+
148
+ edge.label.times do
149
+ begin
150
+ res = edge.pull!(&blk)
151
+ rescue RuntimeError => ex
152
+ # Let's try another Edge, perhaps?
153
+ break
154
+ end
155
+
156
+ # right here we would add the returned resource to the store,
157
+ # but with converters we dont store the resources; we just
158
+ # record that this edge has contributed one resource:
159
+ add_to_contributed_resources!(res, edge)
160
+
161
+ end
162
+
163
+ end
164
+
165
+ end
166
+
167
+ def pull_all!
168
+
169
+ incoming_edges
170
+ .shuffle
171
+ .each do |edge|
172
+ begin
173
+ blk = edge.pull_expression
174
+ rescue RuntimeError => ex
175
+ raise RuntimeError.new "One edge failed to provide an expression; the whole operation failed."
176
+ end
177
+
178
+ edge.label.times do
179
+ begin
180
+ res = edge.pull!(&blk)
181
+ res=nil # we do not store the results
182
+ rescue RuntimeError => ex
183
+ raise RuntimeError.new "One edge failed to pull; the whole operation failed."
184
+ end
185
+
186
+ end
187
+
188
+ end
189
+
190
+ end
191
+
192
+ def push_all!
193
+ outgoing_edges
194
+ .shuffle
195
+ .each do |edge|
196
+ begin
197
+ exp = edge.push_expression
198
+ rescue RuntimeError => ex
199
+ raise RuntimeError.new "One edge failed to provide an expression; the whole operation failed."
200
+ end
201
+
202
+ edge.label.times do
203
+
204
+ begin
205
+ res = make_resource(&exp)
206
+ rescue RuntimeError => ex
207
+ raise RuntimeError.new "This Converter cannot provide any suitable Resource."
208
+ end
209
+
210
+ begin
211
+ edge.push!(res)
212
+ rescue RuntimeError => e
213
+ raise RuntimeError.new e.message+" SO "+"One push over an edge failed; the whole operation failed."
214
+ end
215
+
216
+ end
217
+
218
+ end
219
+
220
+
221
+ end
222
+
223
+ def push_any!
224
+ raise NotImplementedError.new "Converters cannot push_any. Only push_all."
225
+ end
226
+
227
+ # Try to produce a Resource matching given condition.
228
+ #
229
+ # @return [Token] a token resource or any of its subtypes
230
+ # @raise [RuntimeError] in case this Converter cannot produce any
231
+ # Resource that matches the condition.
232
+ def make_resource(&condition)
233
+
234
+ if untyped?
235
+ res = Token.new
236
+ if condition.match_resource?(res)
237
+ res
238
+ else
239
+ raise RuntimeError.new "Failed to make Resource matching given conditions."
240
+ end
241
+ else
242
+ types.shuffle.each do |type|
243
+ res = type.new
244
+ if condition.match_resource?(res)
245
+ return res
246
+ end
247
+ end
248
+ raise RuntimeError.new "Failed to make Resource matching given conditions."
249
+ end
250
+
251
+ end
252
+
253
+ # A Converter may receive its needed resources across turns
254
+ # so there must be a way to keep count of which edges have already
255
+ # 'given their contribution' to this Converter.
256
+ def add_to_contributed_resources!(resource, edge)
257
+ resources_contributed.fetch(edge).put!(resource)
258
+ end
259
+
260
+ def init_resources
261
+ edges.reduce(Hash.new) { |hash, edge| hash.store(edge.object_id, Fifo.new) }
262
+ end
263
+
264
+ def options
265
+ [{name: :required}, :diagram, :mode, :activation, :types]
266
+ end
267
+
268
+ def defaults
269
+ {
270
+ mode: :pull_any,
271
+ activation: :passive,
272
+ types: []
273
+ }
274
+ end
275
+
276
+ end