steep-relaxed 1.9.3.3
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/.gitignore +13 -0
- data/.gitmodules +0 -0
- data/CHANGELOG.md +1032 -0
- data/LICENSE +21 -0
- data/README.md +260 -0
- data/Rakefile +227 -0
- data/STDGEM_DEPENDENCIES.txt +59 -0
- data/Steepfile +68 -0
- data/bin/console +14 -0
- data/bin/generate-diagnostics-docs.rb +112 -0
- data/bin/mem_graph.rb +67 -0
- data/bin/mem_prof.rb +102 -0
- data/bin/output_rebaseline.rb +34 -0
- data/bin/output_test.rb +60 -0
- data/bin/rbs +20 -0
- data/bin/rbs-inline +19 -0
- data/bin/setup +9 -0
- data/bin/stackprof_test.rb +19 -0
- data/bin/steep +19 -0
- data/bin/steep-check.rb +251 -0
- data/bin/steep-prof +16 -0
- data/doc/narrowing.md +195 -0
- data/doc/shape.md +194 -0
- data/exe/steep +18 -0
- data/guides/README.md +5 -0
- data/guides/src/gem-rbs-collection/gem-rbs-collection.md +126 -0
- data/guides/src/getting-started/getting-started.md +163 -0
- data/guides/src/nil-optional/nil-optional.md +195 -0
- data/lib/steep/annotation_parser.rb +199 -0
- data/lib/steep/ast/annotation/collection.rb +172 -0
- data/lib/steep/ast/annotation.rb +137 -0
- data/lib/steep/ast/builtin.rb +104 -0
- data/lib/steep/ast/ignore.rb +148 -0
- data/lib/steep/ast/node/type_application.rb +88 -0
- data/lib/steep/ast/node/type_assertion.rb +81 -0
- data/lib/steep/ast/types/any.rb +35 -0
- data/lib/steep/ast/types/boolean.rb +45 -0
- data/lib/steep/ast/types/bot.rb +35 -0
- data/lib/steep/ast/types/class.rb +43 -0
- data/lib/steep/ast/types/factory.rb +557 -0
- data/lib/steep/ast/types/helper.rb +40 -0
- data/lib/steep/ast/types/instance.rb +42 -0
- data/lib/steep/ast/types/intersection.rb +93 -0
- data/lib/steep/ast/types/literal.rb +59 -0
- data/lib/steep/ast/types/logic.rb +84 -0
- data/lib/steep/ast/types/name.rb +128 -0
- data/lib/steep/ast/types/nil.rb +41 -0
- data/lib/steep/ast/types/proc.rb +117 -0
- data/lib/steep/ast/types/record.rb +79 -0
- data/lib/steep/ast/types/self.rb +43 -0
- data/lib/steep/ast/types/shared_instance.rb +11 -0
- data/lib/steep/ast/types/top.rb +35 -0
- data/lib/steep/ast/types/tuple.rb +60 -0
- data/lib/steep/ast/types/union.rb +97 -0
- data/lib/steep/ast/types/var.rb +65 -0
- data/lib/steep/ast/types/void.rb +35 -0
- data/lib/steep/cli.rb +401 -0
- data/lib/steep/diagnostic/deprecated/else_on_exhaustive_case.rb +20 -0
- data/lib/steep/diagnostic/deprecated/unknown_constant_assigned.rb +28 -0
- data/lib/steep/diagnostic/helper.rb +18 -0
- data/lib/steep/diagnostic/lsp_formatter.rb +78 -0
- data/lib/steep/diagnostic/result_printer2.rb +48 -0
- data/lib/steep/diagnostic/ruby.rb +1221 -0
- data/lib/steep/diagnostic/signature.rb +570 -0
- data/lib/steep/drivers/annotations.rb +52 -0
- data/lib/steep/drivers/check.rb +339 -0
- data/lib/steep/drivers/checkfile.rb +210 -0
- data/lib/steep/drivers/diagnostic_printer.rb +105 -0
- data/lib/steep/drivers/init.rb +66 -0
- data/lib/steep/drivers/langserver.rb +56 -0
- data/lib/steep/drivers/print_project.rb +113 -0
- data/lib/steep/drivers/stats.rb +203 -0
- data/lib/steep/drivers/utils/driver_helper.rb +143 -0
- data/lib/steep/drivers/utils/jobs_option.rb +26 -0
- data/lib/steep/drivers/vendor.rb +27 -0
- data/lib/steep/drivers/watch.rb +194 -0
- data/lib/steep/drivers/worker.rb +58 -0
- data/lib/steep/equatable.rb +23 -0
- data/lib/steep/expectations.rb +228 -0
- data/lib/steep/index/rbs_index.rb +350 -0
- data/lib/steep/index/signature_symbol_provider.rb +185 -0
- data/lib/steep/index/source_index.rb +167 -0
- data/lib/steep/interface/block.rb +103 -0
- data/lib/steep/interface/builder.rb +843 -0
- data/lib/steep/interface/function.rb +1090 -0
- data/lib/steep/interface/method_type.rb +330 -0
- data/lib/steep/interface/shape.rb +239 -0
- data/lib/steep/interface/substitution.rb +159 -0
- data/lib/steep/interface/type_param.rb +115 -0
- data/lib/steep/located_value.rb +20 -0
- data/lib/steep/method_name.rb +42 -0
- data/lib/steep/module_helper.rb +24 -0
- data/lib/steep/node_helper.rb +273 -0
- data/lib/steep/path_helper.rb +30 -0
- data/lib/steep/project/dsl.rb +268 -0
- data/lib/steep/project/group.rb +31 -0
- data/lib/steep/project/options.rb +63 -0
- data/lib/steep/project/pattern.rb +59 -0
- data/lib/steep/project/target.rb +92 -0
- data/lib/steep/project.rb +78 -0
- data/lib/steep/rake_task.rb +132 -0
- data/lib/steep/range_extension.rb +29 -0
- data/lib/steep/server/base_worker.rb +97 -0
- data/lib/steep/server/change_buffer.rb +73 -0
- data/lib/steep/server/custom_methods.rb +77 -0
- data/lib/steep/server/delay_queue.rb +45 -0
- data/lib/steep/server/interaction_worker.rb +492 -0
- data/lib/steep/server/lsp_formatter.rb +455 -0
- data/lib/steep/server/master.rb +922 -0
- data/lib/steep/server/target_group_files.rb +205 -0
- data/lib/steep/server/type_check_controller.rb +366 -0
- data/lib/steep/server/type_check_worker.rb +303 -0
- data/lib/steep/server/work_done_progress.rb +64 -0
- data/lib/steep/server/worker_process.rb +176 -0
- data/lib/steep/services/completion_provider.rb +802 -0
- data/lib/steep/services/content_change.rb +61 -0
- data/lib/steep/services/file_loader.rb +74 -0
- data/lib/steep/services/goto_service.rb +441 -0
- data/lib/steep/services/hover_provider/rbs.rb +88 -0
- data/lib/steep/services/hover_provider/ruby.rb +221 -0
- data/lib/steep/services/hover_provider/singleton_methods.rb +20 -0
- data/lib/steep/services/path_assignment.rb +46 -0
- data/lib/steep/services/signature_help_provider.rb +202 -0
- data/lib/steep/services/signature_service.rb +428 -0
- data/lib/steep/services/stats_calculator.rb +68 -0
- data/lib/steep/services/type_check_service.rb +394 -0
- data/lib/steep/services/type_name_completion.rb +236 -0
- data/lib/steep/signature/validator.rb +651 -0
- data/lib/steep/source/ignore_ranges.rb +69 -0
- data/lib/steep/source.rb +691 -0
- data/lib/steep/subtyping/cache.rb +30 -0
- data/lib/steep/subtyping/check.rb +1113 -0
- data/lib/steep/subtyping/constraints.rb +341 -0
- data/lib/steep/subtyping/relation.rb +101 -0
- data/lib/steep/subtyping/result.rb +324 -0
- data/lib/steep/subtyping/variable_variance.rb +89 -0
- data/lib/steep/test.rb +9 -0
- data/lib/steep/thread_waiter.rb +43 -0
- data/lib/steep/type_construction.rb +5183 -0
- data/lib/steep/type_inference/block_params.rb +416 -0
- data/lib/steep/type_inference/case_when.rb +303 -0
- data/lib/steep/type_inference/constant_env.rb +56 -0
- data/lib/steep/type_inference/context.rb +195 -0
- data/lib/steep/type_inference/logic_type_interpreter.rb +613 -0
- data/lib/steep/type_inference/method_call.rb +193 -0
- data/lib/steep/type_inference/method_params.rb +531 -0
- data/lib/steep/type_inference/multiple_assignment.rb +194 -0
- data/lib/steep/type_inference/send_args.rb +712 -0
- data/lib/steep/type_inference/type_env.rb +341 -0
- data/lib/steep/type_inference/type_env_builder.rb +138 -0
- data/lib/steep/typing.rb +321 -0
- data/lib/steep/version.rb +3 -0
- data/lib/steep.rb +369 -0
- data/manual/annotations.md +181 -0
- data/manual/ignore.md +20 -0
- data/manual/ruby-diagnostics.md +1879 -0
- data/sample/Steepfile +22 -0
- data/sample/lib/conference.rb +49 -0
- data/sample/lib/length.rb +35 -0
- data/sample/sig/conference.rbs +42 -0
- data/sample/sig/generics.rbs +15 -0
- data/sample/sig/length.rbs +34 -0
- data/steep-relaxed.gemspec +56 -0
- metadata +340 -0
@@ -0,0 +1,324 @@
|
|
1
|
+
module Steep
|
2
|
+
module Subtyping
|
3
|
+
module Result
|
4
|
+
class Base
|
5
|
+
attr_reader :relation
|
6
|
+
|
7
|
+
def initialize(relation)
|
8
|
+
@relation = relation
|
9
|
+
end
|
10
|
+
|
11
|
+
def failure?
|
12
|
+
!success?
|
13
|
+
end
|
14
|
+
|
15
|
+
def then
|
16
|
+
if success?
|
17
|
+
yield self
|
18
|
+
self
|
19
|
+
else
|
20
|
+
self
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def else
|
25
|
+
if failure?
|
26
|
+
yield self
|
27
|
+
self
|
28
|
+
else
|
29
|
+
self
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def failure_path(path = [])
|
34
|
+
raise
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class Skip < Base
|
39
|
+
def success?
|
40
|
+
false
|
41
|
+
end
|
42
|
+
|
43
|
+
def failure?
|
44
|
+
false
|
45
|
+
end
|
46
|
+
|
47
|
+
def failure_path(path = [])
|
48
|
+
raise
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class Expand < Base
|
53
|
+
attr_reader :child
|
54
|
+
|
55
|
+
def initialize(relation, &block)
|
56
|
+
super relation
|
57
|
+
@child = yield relation
|
58
|
+
|
59
|
+
raise if @child == true
|
60
|
+
end
|
61
|
+
|
62
|
+
def success?
|
63
|
+
child.success?
|
64
|
+
end
|
65
|
+
|
66
|
+
def failure_path(path = [])
|
67
|
+
if child.failure?
|
68
|
+
path.unshift(self)
|
69
|
+
child.failure_path(path)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class All < Base
|
75
|
+
attr_reader :branches
|
76
|
+
|
77
|
+
def initialize(relation)
|
78
|
+
super relation
|
79
|
+
@branches = []
|
80
|
+
@failure = false
|
81
|
+
end
|
82
|
+
|
83
|
+
# Returns `false` if no future `#add` changes the result.
|
84
|
+
def add(*relations, &block)
|
85
|
+
relations.each do |relation|
|
86
|
+
if success?
|
87
|
+
result = yield(relation)
|
88
|
+
if result
|
89
|
+
branches << result
|
90
|
+
end
|
91
|
+
else
|
92
|
+
# Already failed.
|
93
|
+
branches << Skip.new(relation)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# No need to test more branches if already failed.
|
98
|
+
success?
|
99
|
+
end
|
100
|
+
|
101
|
+
def add_result(result)
|
102
|
+
if result
|
103
|
+
add(result.relation) { result }
|
104
|
+
else
|
105
|
+
success?
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def success?
|
110
|
+
!failure?
|
111
|
+
end
|
112
|
+
|
113
|
+
def failure?
|
114
|
+
@failure ||= branches.any?(&:failure?)
|
115
|
+
end
|
116
|
+
|
117
|
+
def failure_path(path = [])
|
118
|
+
if failure?
|
119
|
+
r = branches.find(&:failure?) or raise
|
120
|
+
path.unshift(self)
|
121
|
+
r.failure_path(path)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
class Any < Base
|
127
|
+
attr_reader :branches
|
128
|
+
|
129
|
+
def initialize(relation)
|
130
|
+
super relation
|
131
|
+
@branches = []
|
132
|
+
@success = false
|
133
|
+
end
|
134
|
+
|
135
|
+
# Returns `false` if no future `#add` changes the result.
|
136
|
+
def add(*relations, &block)
|
137
|
+
relations.each do |relation|
|
138
|
+
if failure?
|
139
|
+
result = yield(relation)
|
140
|
+
branches << result
|
141
|
+
else
|
142
|
+
# Already succeeded.
|
143
|
+
branches << Skip.new(relation)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# No need to test more branches if already succeeded.
|
148
|
+
failure?
|
149
|
+
end
|
150
|
+
|
151
|
+
def success?
|
152
|
+
@success ||= branches.any?(&:success?)
|
153
|
+
end
|
154
|
+
|
155
|
+
def failure_path(path = [])
|
156
|
+
if failure?
|
157
|
+
path.unshift(self)
|
158
|
+
if r = branches.find(&:failure?)
|
159
|
+
r.failure_path(path)
|
160
|
+
else
|
161
|
+
path
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
class Success < Base
|
168
|
+
def success?
|
169
|
+
true
|
170
|
+
end
|
171
|
+
|
172
|
+
def failure_path(path = [])
|
173
|
+
nil
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
class Failure < Base
|
178
|
+
class MethodMissingError
|
179
|
+
attr_reader :name
|
180
|
+
|
181
|
+
def initialize(name:)
|
182
|
+
@name = name
|
183
|
+
end
|
184
|
+
|
185
|
+
def message
|
186
|
+
"Method #{name} is missing"
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
class BlockMismatchError
|
191
|
+
attr_reader :name
|
192
|
+
|
193
|
+
def initialize(name:)
|
194
|
+
@name = name
|
195
|
+
end
|
196
|
+
|
197
|
+
def message
|
198
|
+
"Method #{name} is incompatible for block"
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
class ParameterMismatchError
|
203
|
+
attr_reader :name
|
204
|
+
|
205
|
+
def initialize(name:)
|
206
|
+
@name = name
|
207
|
+
end
|
208
|
+
|
209
|
+
def message
|
210
|
+
"Method #{name} or its block has incompatible parameters"
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
class UnknownPairError
|
215
|
+
attr_reader :relation
|
216
|
+
|
217
|
+
def initialize(relation:)
|
218
|
+
@relation = relation
|
219
|
+
end
|
220
|
+
|
221
|
+
def message
|
222
|
+
"#{relation} does not hold"
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
class PolyMethodSubtyping
|
227
|
+
attr_reader :name
|
228
|
+
|
229
|
+
def initialize(name:)
|
230
|
+
@name = name
|
231
|
+
end
|
232
|
+
|
233
|
+
def message
|
234
|
+
"Method #{name} requires uncheckable polymorphic subtyping"
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
class UnsatisfiedConstraints
|
239
|
+
attr_reader :error
|
240
|
+
|
241
|
+
def initialize(error)
|
242
|
+
@error = error
|
243
|
+
end
|
244
|
+
|
245
|
+
def var
|
246
|
+
error.var
|
247
|
+
end
|
248
|
+
|
249
|
+
def sub_type
|
250
|
+
error.sub_type
|
251
|
+
end
|
252
|
+
|
253
|
+
def super_type
|
254
|
+
error.super_type
|
255
|
+
end
|
256
|
+
|
257
|
+
def result
|
258
|
+
error.result
|
259
|
+
end
|
260
|
+
|
261
|
+
def message
|
262
|
+
"A constraint on #{var} cannot be solved: #{sub_type} <: #{super_type}"
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
class SelfBindingMismatch
|
267
|
+
def message
|
268
|
+
"Self binding is incompatible"
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
class LoopAbort
|
273
|
+
def message
|
274
|
+
"Detected infinite loop with limit of `#{Check::ABORT_LIMIT}`; specify $STEEP_SUBTYPING_ABORT_LIMIT env var to override the limit."
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
attr_reader :error
|
279
|
+
|
280
|
+
def initialize(relation, error)
|
281
|
+
super relation
|
282
|
+
@error = error
|
283
|
+
end
|
284
|
+
|
285
|
+
def success?
|
286
|
+
false
|
287
|
+
end
|
288
|
+
|
289
|
+
def failure_path(path = [])
|
290
|
+
path.unshift(self)
|
291
|
+
path
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
module Helper
|
296
|
+
def Skip(relation)
|
297
|
+
Skip.new(relation)
|
298
|
+
end
|
299
|
+
|
300
|
+
def Expand(relation, &block)
|
301
|
+
Expand.new(relation, &block)
|
302
|
+
end
|
303
|
+
|
304
|
+
def All(relation, &block)
|
305
|
+
All.new(relation).tap(&block)
|
306
|
+
end
|
307
|
+
|
308
|
+
def Any(relation, &block)
|
309
|
+
Any.new(relation).tap(&block)
|
310
|
+
end
|
311
|
+
|
312
|
+
def Success(relation)
|
313
|
+
Success.new(relation)
|
314
|
+
end
|
315
|
+
|
316
|
+
alias success Success
|
317
|
+
|
318
|
+
def Failure(relation, error = nil)
|
319
|
+
Failure.new(relation, error || yield)
|
320
|
+
end
|
321
|
+
end
|
322
|
+
end
|
323
|
+
end
|
324
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module Steep
|
2
|
+
module Subtyping
|
3
|
+
class VariableVariance
|
4
|
+
attr_reader :covariants
|
5
|
+
attr_reader :contravariants
|
6
|
+
|
7
|
+
def initialize(covariants:, contravariants:)
|
8
|
+
@covariants = covariants
|
9
|
+
@contravariants = contravariants
|
10
|
+
end
|
11
|
+
|
12
|
+
def covariant?(var)
|
13
|
+
covariants.member?(var) && !contravariants.member?(var)
|
14
|
+
end
|
15
|
+
|
16
|
+
def contravariant?(var)
|
17
|
+
contravariants.member?(var) && !covariants.member?(var)
|
18
|
+
end
|
19
|
+
|
20
|
+
def invariant?(var)
|
21
|
+
covariants.member?(var) && contravariants.member?(var)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.from_type(type)
|
25
|
+
covariants = Set.new
|
26
|
+
contravariants = Set.new
|
27
|
+
|
28
|
+
add_type(type, variance: :covariant, covariants: covariants, contravariants: contravariants)
|
29
|
+
|
30
|
+
new(covariants: covariants, contravariants: contravariants)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.from_method_type(method_type)
|
34
|
+
covariants = Set.new
|
35
|
+
contravariants = Set.new
|
36
|
+
|
37
|
+
add_params(method_type.type.params, block: false, contravariants: contravariants, covariants: covariants)
|
38
|
+
add_type(method_type.type.return_type, variance: :covariant, covariants: covariants, contravariants: contravariants)
|
39
|
+
|
40
|
+
method_type.block&.type&.yield_self do |proc|
|
41
|
+
add_params(proc.params, block: true, contravariants: contravariants, covariants: covariants)
|
42
|
+
add_type(proc.return_type, variance: :contravariant, covariants: covariants, contravariants: contravariants)
|
43
|
+
end
|
44
|
+
|
45
|
+
new(covariants: covariants, contravariants: contravariants)
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.add_params(params, block:, covariants:, contravariants:)
|
49
|
+
params&.each_type do |type|
|
50
|
+
add_type(type, variance: block ? :contravariant : :covariant, covariants: covariants, contravariants: contravariants)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.add_type(type, variance:, covariants:, contravariants:)
|
55
|
+
case type
|
56
|
+
when AST::Types::Var
|
57
|
+
case variance
|
58
|
+
when :covariant
|
59
|
+
covariants << type.name
|
60
|
+
when :contravariant
|
61
|
+
contravariants << type.name
|
62
|
+
when :invariant
|
63
|
+
covariants << type.name
|
64
|
+
contravariants << type.name
|
65
|
+
end
|
66
|
+
when AST::Types::Proc
|
67
|
+
type.type.params&.each_type do |type|
|
68
|
+
add_type(type, variance: variance, covariants: contravariants, contravariants: covariants)
|
69
|
+
end
|
70
|
+
add_type(type.type.return_type, variance: variance, covariants: covariants, contravariants: contravariants)
|
71
|
+
if type.block
|
72
|
+
type.block.type.params&.each_type do |type|
|
73
|
+
add_type(type, variance: variance, covariants: covariants, contravariants: contravariants)
|
74
|
+
end
|
75
|
+
add_type(type.type.return_type, variance: variance, covariants: contravariants, contravariants: covariants)
|
76
|
+
end
|
77
|
+
when AST::Types::Union, AST::Types::Intersection, AST::Types::Tuple
|
78
|
+
type.types.each do |ty|
|
79
|
+
add_type(ty, variance: variance, covariants: covariants, contravariants: contravariants)
|
80
|
+
end
|
81
|
+
when AST::Types::Name::Interface, AST::Types::Name::Instance, AST::Types::Name::Alias
|
82
|
+
type.args.each do |arg|
|
83
|
+
add_type(arg, variance: :invariant, covariants: covariants, contravariants: contravariants)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
data/lib/steep/test.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
module Steep
|
2
|
+
class ThreadWaiter
|
3
|
+
attr_reader :queue, :waiter_threads
|
4
|
+
|
5
|
+
def initialize(objects = nil)
|
6
|
+
@queue = Thread::Queue.new()
|
7
|
+
@waiter_threads = Set[].compare_by_identity
|
8
|
+
|
9
|
+
if objects
|
10
|
+
objects.each do |object|
|
11
|
+
thread = yield(object)
|
12
|
+
self << thread
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def <<(thread)
|
18
|
+
waiter_thread = Thread.new(thread) do |thread|
|
19
|
+
# @type var thread: Thread
|
20
|
+
|
21
|
+
Thread.current.report_on_exception = false
|
22
|
+
|
23
|
+
begin
|
24
|
+
thread.join
|
25
|
+
ensure
|
26
|
+
queue << thread
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
waiter_threads << waiter_thread
|
31
|
+
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def wait_one
|
36
|
+
unless waiter_threads.empty?
|
37
|
+
th = queue.pop() or raise
|
38
|
+
waiter_threads.delete(th)
|
39
|
+
th
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|