rbs 3.10.0 → 4.0.0.dev.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.
- checksums.yaml +4 -4
- data/.github/workflows/comments.yml +3 -3
- data/.github/workflows/ruby.yml +24 -35
- data/.github/workflows/typecheck.yml +3 -1
- data/.github/workflows/windows.yml +2 -2
- data/.gitignore +0 -4
- data/CHANGELOG.md +0 -88
- data/README.md +1 -38
- data/Rakefile +20 -142
- data/Steepfile +1 -0
- data/config.yml +43 -1
- data/core/array.rbs +46 -100
- data/core/complex.rbs +21 -32
- data/core/dir.rbs +2 -2
- data/core/encoding.rbs +9 -6
- data/core/enumerable.rbs +3 -90
- data/core/enumerator.rbs +1 -18
- data/core/errno.rbs +0 -8
- data/core/errors.rbs +1 -28
- data/core/exception.rbs +2 -2
- data/core/fiber.rbs +4 -5
- data/core/file.rbs +12 -27
- data/core/file_test.rbs +1 -1
- data/core/float.rbs +22 -209
- data/core/gc.rbs +281 -417
- data/core/hash.rbs +727 -1024
- data/core/integer.rbs +38 -78
- data/core/io/buffer.rbs +7 -18
- data/core/io/wait.rbs +33 -11
- data/core/io.rbs +12 -14
- data/core/kernel.rbs +51 -57
- data/core/marshal.rbs +1 -1
- data/core/match_data.rbs +1 -1
- data/core/math.rbs +3 -42
- data/core/method.rbs +6 -14
- data/core/module.rbs +17 -88
- data/core/nil_class.rbs +3 -3
- data/core/numeric.rbs +16 -16
- data/core/object.rbs +3 -3
- data/core/object_space.rbs +15 -21
- data/core/proc.rbs +8 -15
- data/core/process.rbs +2 -2
- data/core/ractor.rbs +437 -278
- data/core/range.rbs +8 -7
- data/core/rational.rbs +24 -37
- data/core/rbs/unnamed/argf.rbs +2 -2
- data/core/rbs/unnamed/env_class.rbs +1 -1
- data/core/rbs/unnamed/random.rbs +2 -4
- data/core/regexp.rbs +20 -25
- data/core/ruby_vm.rbs +4 -6
- data/core/rubygems/errors.rbs +70 -3
- data/core/rubygems/rubygems.rbs +79 -11
- data/core/rubygems/version.rbs +3 -2
- data/core/set.rbs +359 -488
- data/core/string.rbs +1228 -3153
- data/core/struct.rbs +1 -1
- data/core/symbol.rbs +4 -4
- data/core/thread.rbs +29 -92
- data/core/time.rbs +9 -35
- data/core/trace_point.rbs +4 -7
- data/core/unbound_method.rbs +6 -14
- data/docs/collection.md +2 -2
- data/docs/gem.md +1 -0
- data/docs/sigs.md +3 -3
- data/ext/rbs_extension/ast_translation.c +1077 -944
- data/ext/rbs_extension/ast_translation.h +0 -7
- data/ext/rbs_extension/class_constants.c +83 -71
- data/ext/rbs_extension/class_constants.h +7 -4
- data/ext/rbs_extension/extconf.rb +2 -24
- data/ext/rbs_extension/legacy_location.c +172 -173
- data/ext/rbs_extension/legacy_location.h +3 -8
- data/ext/rbs_extension/main.c +289 -239
- data/ext/rbs_extension/rbs_extension.h +0 -3
- data/ext/rbs_extension/rbs_string_bridging.h +0 -4
- data/include/rbs/ast.h +98 -37
- data/include/rbs/defines.h +12 -38
- data/include/rbs/lexer.h +114 -126
- data/include/rbs/location.h +14 -14
- data/include/rbs/parser.h +37 -21
- data/include/rbs/string.h +5 -3
- data/include/rbs/util/rbs_allocator.h +19 -40
- data/include/rbs/util/rbs_assert.h +1 -12
- data/include/rbs/util/rbs_constant_pool.h +3 -3
- data/include/rbs/util/rbs_encoding.h +1 -3
- data/include/rbs/util/rbs_unescape.h +1 -2
- data/lib/rbs/ast/ruby/annotations.rb +119 -0
- data/lib/rbs/ast/ruby/comment_block.rb +221 -0
- data/lib/rbs/ast/ruby/declarations.rb +86 -0
- data/lib/rbs/ast/ruby/helpers/constant_helper.rb +24 -0
- data/lib/rbs/ast/ruby/helpers/location_helper.rb +15 -0
- data/lib/rbs/ast/ruby/members.rb +213 -0
- data/lib/rbs/buffer.rb +104 -24
- data/lib/rbs/cli/validate.rb +40 -35
- data/lib/rbs/cli.rb +5 -6
- data/lib/rbs/collection/config/lockfile_generator.rb +0 -1
- data/lib/rbs/collection.rb +0 -1
- data/lib/rbs/definition.rb +6 -1
- data/lib/rbs/definition_builder/ancestor_builder.rb +65 -62
- data/lib/rbs/definition_builder/method_builder.rb +45 -30
- data/lib/rbs/definition_builder.rb +44 -9
- data/lib/rbs/environment/class_entry.rb +69 -0
- data/lib/rbs/environment/module_entry.rb +66 -0
- data/lib/rbs/environment.rb +244 -218
- data/lib/rbs/environment_loader.rb +3 -3
- data/lib/rbs/errors.rb +5 -4
- data/lib/rbs/inline_parser/comment_association.rb +117 -0
- data/lib/rbs/inline_parser.rb +206 -0
- data/lib/rbs/location_aux.rb +35 -3
- data/lib/rbs/parser_aux.rb +11 -6
- data/lib/rbs/prototype/runtime.rb +2 -2
- data/lib/rbs/resolver/constant_resolver.rb +2 -2
- data/lib/rbs/resolver/type_name_resolver.rb +38 -124
- data/lib/rbs/source.rb +99 -0
- data/lib/rbs/subtractor.rb +4 -3
- data/lib/rbs/test/type_check.rb +0 -14
- data/lib/rbs/types.rb +1 -3
- data/lib/rbs/version.rb +1 -1
- data/lib/rbs.rb +13 -1
- data/lib/rdoc/discover.rb +1 -1
- data/lib/rdoc_plugin/parser.rb +1 -1
- data/rbs.gemspec +1 -0
- data/sig/ancestor_builder.rbs +1 -1
- data/sig/ast/ruby/annotations.rbs +110 -0
- data/sig/ast/ruby/comment_block.rbs +119 -0
- data/sig/ast/ruby/declarations.rbs +60 -0
- data/sig/ast/ruby/helpers/constant_helper.rbs +11 -0
- data/sig/ast/ruby/helpers/location_helper.rbs +15 -0
- data/sig/ast/ruby/members.rbs +72 -0
- data/sig/buffer.rbs +63 -5
- data/sig/definition.rbs +1 -0
- data/sig/definition_builder.rbs +1 -1
- data/sig/environment/class_entry.rbs +50 -0
- data/sig/environment/module_entry.rbs +50 -0
- data/sig/environment.rbs +28 -133
- data/sig/errors.rbs +13 -6
- data/sig/inline_parser/comment_association.rbs +71 -0
- data/sig/inline_parser.rbs +87 -0
- data/sig/location.rbs +32 -7
- data/sig/manifest.yaml +1 -0
- data/sig/method_builder.rbs +7 -4
- data/sig/parser.rbs +16 -20
- data/sig/resolver/type_name_resolver.rbs +7 -38
- data/sig/source.rbs +48 -0
- data/sig/types.rbs +1 -4
- data/src/ast.c +290 -201
- data/src/lexer.c +2813 -2902
- data/src/lexer.re +4 -0
- data/src/lexstate.c +155 -169
- data/src/location.c +40 -40
- data/src/parser.c +2665 -2433
- data/src/string.c +48 -0
- data/src/util/rbs_allocator.c +77 -80
- data/src/util/rbs_assert.c +10 -10
- data/src/util/rbs_buffer.c +2 -2
- data/src/util/rbs_constant_pool.c +15 -13
- data/src/util/rbs_encoding.c +4062 -20097
- data/src/util/rbs_unescape.c +48 -85
- data/stdlib/bigdecimal/0/big_decimal.rbs +82 -100
- data/stdlib/bigdecimal-math/0/big_math.rbs +8 -169
- data/stdlib/cgi/0/core.rbs +396 -2
- data/stdlib/cgi/0/manifest.yaml +0 -1
- data/stdlib/coverage/0/coverage.rbs +1 -3
- data/stdlib/date/0/date.rbs +59 -67
- data/stdlib/date/0/date_time.rbs +1 -1
- data/stdlib/delegate/0/delegator.rbs +7 -10
- data/stdlib/erb/0/erb.rbs +347 -737
- data/stdlib/fileutils/0/fileutils.rbs +13 -18
- data/stdlib/forwardable/0/forwardable.rbs +0 -3
- data/stdlib/json/0/json.rbs +48 -68
- data/stdlib/net-http/0/net-http.rbs +0 -3
- data/stdlib/objspace/0/objspace.rbs +4 -9
- data/stdlib/open-uri/0/open-uri.rbs +0 -40
- data/stdlib/openssl/0/openssl.rbs +228 -331
- data/stdlib/optparse/0/optparse.rbs +3 -3
- data/{core → stdlib/pathname/0}/pathname.rbs +355 -255
- data/stdlib/psych/0/psych.rbs +3 -3
- data/stdlib/rdoc/0/rdoc.rbs +1 -1
- data/stdlib/resolv/0/resolv.rbs +68 -25
- data/stdlib/ripper/0/ripper.rbs +2 -5
- data/stdlib/singleton/0/singleton.rbs +0 -3
- data/stdlib/socket/0/socket.rbs +1 -13
- data/stdlib/socket/0/tcp_socket.rbs +2 -10
- data/stdlib/stringio/0/stringio.rbs +85 -1176
- data/stdlib/strscan/0/string_scanner.rbs +31 -31
- data/stdlib/tempfile/0/tempfile.rbs +3 -3
- data/stdlib/time/0/time.rbs +1 -1
- data/stdlib/timeout/0/timeout.rbs +7 -63
- data/stdlib/tsort/0/cyclic.rbs +0 -3
- data/stdlib/uri/0/common.rbs +2 -11
- data/stdlib/uri/0/file.rbs +1 -1
- data/stdlib/uri/0/generic.rbs +16 -17
- data/stdlib/uri/0/rfc2396_parser.rbs +7 -6
- data/stdlib/zlib/0/zstream.rbs +0 -1
- metadata +40 -12
- data/.clang-format +0 -74
- data/.clangd +0 -2
- data/.github/workflows/c-check.yml +0 -54
- data/core/ruby.rbs +0 -53
- data/docs/aliases.md +0 -79
- data/docs/encoding.md +0 -56
- data/ext/rbs_extension/compat.h +0 -10
- data/stdlib/cgi-escape/0/escape.rbs +0 -153
data/core/ractor.rbs
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
# <!-- rdoc-file=ractor.rb -->
|
|
2
|
+
# Ractor is an Actor-model abstraction for Ruby that provides thread-safe
|
|
3
|
+
# parallel execution.
|
|
4
|
+
#
|
|
2
5
|
# Ractor.new makes a new Ractor, which can run in parallel.
|
|
3
6
|
#
|
|
4
7
|
# # The simplest ractor
|
|
5
8
|
# r = Ractor.new {puts "I am in Ractor!"}
|
|
6
|
-
# r.
|
|
9
|
+
# r.take # wait for it to finish
|
|
7
10
|
# # Here, "I am in Ractor!" is printed
|
|
8
11
|
#
|
|
9
12
|
# Ractors do not share all objects with each other. There are two main benefits
|
|
@@ -37,12 +40,55 @@
|
|
|
37
40
|
# puts "I am in Ractor! a=#{a_in_ractor}"
|
|
38
41
|
# end
|
|
39
42
|
# r.send(a) # pass it
|
|
40
|
-
# r.
|
|
43
|
+
# r.take
|
|
41
44
|
# # Here, "I am in Ractor! a=1" is printed
|
|
42
45
|
#
|
|
46
|
+
# There are two pairs of methods for sending/receiving messages:
|
|
47
|
+
#
|
|
48
|
+
# * Ractor#send and Ractor.receive for when the *sender* knows the receiver
|
|
49
|
+
# (push);
|
|
50
|
+
# * Ractor.yield and Ractor#take for when the *receiver* knows the sender
|
|
51
|
+
# (pull);
|
|
52
|
+
#
|
|
43
53
|
# In addition to that, any arguments passed to Ractor.new are passed to the
|
|
44
54
|
# block and available there as if received by Ractor.receive, and the last block
|
|
45
|
-
# value
|
|
55
|
+
# value is sent outside of the ractor as if sent by Ractor.yield.
|
|
56
|
+
#
|
|
57
|
+
# A little demonstration of a classic ping-pong:
|
|
58
|
+
#
|
|
59
|
+
# server = Ractor.new(name: "server") do
|
|
60
|
+
# puts "Server starts: #{self.inspect}"
|
|
61
|
+
# puts "Server sends: ping"
|
|
62
|
+
# Ractor.yield 'ping' # The server doesn't know the receiver and sends to whoever interested
|
|
63
|
+
# received = Ractor.receive # The server doesn't know the sender and receives from whoever sent
|
|
64
|
+
# puts "Server received: #{received}"
|
|
65
|
+
# end
|
|
66
|
+
#
|
|
67
|
+
# client = Ractor.new(server) do |srv| # The server is sent to the client, and available as srv
|
|
68
|
+
# puts "Client starts: #{self.inspect}"
|
|
69
|
+
# received = srv.take # The client takes a message from the server
|
|
70
|
+
# puts "Client received from " \
|
|
71
|
+
# "#{srv.inspect}: #{received}"
|
|
72
|
+
# puts "Client sends to " \
|
|
73
|
+
# "#{srv.inspect}: pong"
|
|
74
|
+
# srv.send 'pong' # The client sends a message to the server
|
|
75
|
+
# end
|
|
76
|
+
#
|
|
77
|
+
# [client, server].each(&:take) # Wait until they both finish
|
|
78
|
+
#
|
|
79
|
+
# This will output something like:
|
|
80
|
+
#
|
|
81
|
+
# Server starts: #<Ractor:#2 server test.rb:1 running>
|
|
82
|
+
# Server sends: ping
|
|
83
|
+
# Client starts: #<Ractor:#3 test.rb:8 running>
|
|
84
|
+
# Client received from #<Ractor:#2 server test.rb:1 blocking>: ping
|
|
85
|
+
# Client sends to #<Ractor:#2 server test.rb:1 blocking>: pong
|
|
86
|
+
# Server received: pong
|
|
87
|
+
#
|
|
88
|
+
# Ractors receive their messages via the *incoming port*, and send them to the
|
|
89
|
+
# *outgoing port*. Either one can be disabled with Ractor#close_incoming and
|
|
90
|
+
# Ractor#close_outgoing, respectively. When a ractor terminates, its ports are
|
|
91
|
+
# closed automatically.
|
|
46
92
|
#
|
|
47
93
|
# ## Shareable and unshareable objects
|
|
48
94
|
#
|
|
@@ -82,7 +128,7 @@
|
|
|
82
128
|
# puts "In ractor: #{data2.object_id}, #{data2[0].object_id}, #{data2[1].object_id}"
|
|
83
129
|
# end
|
|
84
130
|
# r.send(data)
|
|
85
|
-
# r.
|
|
131
|
+
# r.take
|
|
86
132
|
# puts "Outside : #{data.object_id}, #{data[0].object_id}, #{data[1].object_id}"
|
|
87
133
|
#
|
|
88
134
|
# This will output something like:
|
|
@@ -105,7 +151,7 @@
|
|
|
105
151
|
# puts "In ractor: #{data_in_ractor.object_id}, #{data_in_ractor[0].object_id}"
|
|
106
152
|
# end
|
|
107
153
|
# r.send(data, move: true)
|
|
108
|
-
# r.
|
|
154
|
+
# r.take
|
|
109
155
|
# puts "Outside: moved? #{Ractor::MovedObject === data}"
|
|
110
156
|
# puts "Outside: #{data.inspect}"
|
|
111
157
|
#
|
|
@@ -118,7 +164,7 @@
|
|
|
118
164
|
# Notice that even `inspect` (and more basic methods like `__id__`) is
|
|
119
165
|
# inaccessible on a moved object.
|
|
120
166
|
#
|
|
121
|
-
#
|
|
167
|
+
# Class and Module objects are shareable so the class/module definitions are
|
|
122
168
|
# shared between ractors. Ractor objects are also shareable. All operations on
|
|
123
169
|
# shareable objects are thread-safe, so the thread-safety property will be kept.
|
|
124
170
|
# We can not define mutable shareable objects in Ruby, but C extensions can
|
|
@@ -143,7 +189,7 @@
|
|
|
143
189
|
# puts "I can't see #{cls.tricky}"
|
|
144
190
|
# cls.tricky = true # doesn't get here, but this would also raise an error
|
|
145
191
|
# end
|
|
146
|
-
# r.
|
|
192
|
+
# r.take
|
|
147
193
|
# # I see C
|
|
148
194
|
# # can not access instance variables of classes/modules from non-main Ractors (RuntimeError)
|
|
149
195
|
#
|
|
@@ -157,7 +203,7 @@
|
|
|
157
203
|
# puts "GOOD=#{GOOD}"
|
|
158
204
|
# puts "BAD=#{BAD}"
|
|
159
205
|
# end
|
|
160
|
-
# r.
|
|
206
|
+
# r.take
|
|
161
207
|
# # GOOD=good
|
|
162
208
|
# # can not access non-shareable objects in constant Object::BAD by non-main Ractor. (NameError)
|
|
163
209
|
#
|
|
@@ -167,7 +213,7 @@
|
|
|
167
213
|
# puts "I see #{C}"
|
|
168
214
|
# puts "I can't see #{C.tricky}"
|
|
169
215
|
# end
|
|
170
|
-
# r.
|
|
216
|
+
# r.take
|
|
171
217
|
# # I see C
|
|
172
218
|
# # can not access instance variables of classes/modules from non-main Ractors (RuntimeError)
|
|
173
219
|
#
|
|
@@ -183,7 +229,7 @@
|
|
|
183
229
|
# a = 1
|
|
184
230
|
# Thread.new {puts "Thread in ractor: a=#{a}"}.join
|
|
185
231
|
# end
|
|
186
|
-
# r.
|
|
232
|
+
# r.take
|
|
187
233
|
# # Here "Thread in ractor: a=1" will be printed
|
|
188
234
|
#
|
|
189
235
|
# ## Note on code examples
|
|
@@ -196,7 +242,7 @@
|
|
|
196
242
|
# end
|
|
197
243
|
#
|
|
198
244
|
# It is **only for demonstration purposes** and shouldn't be used in a real
|
|
199
|
-
# code. Most of the time, #
|
|
245
|
+
# code. Most of the time, #take is used to wait for ractors to finish.
|
|
200
246
|
#
|
|
201
247
|
# ## Reference
|
|
202
248
|
#
|
|
@@ -234,10 +280,10 @@ class Ractor
|
|
|
234
280
|
# Returns the number of Ractors currently running or blocking (waiting).
|
|
235
281
|
#
|
|
236
282
|
# Ractor.count #=> 1
|
|
237
|
-
# r = Ractor.new(name: 'example') { Ractor.
|
|
283
|
+
# r = Ractor.new(name: 'example') { Ractor.yield(1) }
|
|
238
284
|
# Ractor.count #=> 2 (main + example ractor)
|
|
239
|
-
# r
|
|
240
|
-
# r.
|
|
285
|
+
# r.take # wait for Ractor.yield(1)
|
|
286
|
+
# r.take # wait until r will finish
|
|
241
287
|
# Ractor.count #=> 1
|
|
242
288
|
#
|
|
243
289
|
def self.count: () -> Integer
|
|
@@ -317,7 +363,7 @@ class Ractor
|
|
|
317
363
|
# `self` inside the block will refer to the current Ractor.
|
|
318
364
|
#
|
|
319
365
|
# r = Ractor.new { puts "Hi, I am #{self.inspect}" }
|
|
320
|
-
# r.
|
|
366
|
+
# r.take
|
|
321
367
|
# # Prints "Hi, I am #<Ractor:#2 test.rb:1 running>"
|
|
322
368
|
#
|
|
323
369
|
# Any `args` passed are propagated to the block arguments by the same rules as
|
|
@@ -329,14 +375,14 @@ class Ractor
|
|
|
329
375
|
# r = Ractor.new(arg) {|received_arg|
|
|
330
376
|
# puts "Received: #{received_arg} (##{received_arg.object_id})"
|
|
331
377
|
# }
|
|
332
|
-
# r.
|
|
378
|
+
# r.take
|
|
333
379
|
# # Prints:
|
|
334
380
|
# # Passing: [1, 2, 3] (#280)
|
|
335
381
|
# # Received: [1, 2, 3] (#300)
|
|
336
382
|
#
|
|
337
383
|
# Ractor's `name` can be set for debugging purposes:
|
|
338
384
|
#
|
|
339
|
-
# r = Ractor.new(name: 'my ractor') {}; r.
|
|
385
|
+
# r = Ractor.new(name: 'my ractor') {}; r.take
|
|
340
386
|
# p r
|
|
341
387
|
# #=> #<Ractor:#3 my ractor test.rb:1 terminated>
|
|
342
388
|
#
|
|
@@ -344,77 +390,209 @@ class Ractor
|
|
|
344
390
|
|
|
345
391
|
# <!--
|
|
346
392
|
# rdoc-file=ractor.rb
|
|
347
|
-
# - Ractor.receive ->
|
|
393
|
+
# - Ractor.receive -> msg
|
|
348
394
|
# -->
|
|
349
|
-
# Receive a message from the
|
|
395
|
+
# Receive a message from the incoming port of the current ractor (which was sent
|
|
396
|
+
# there by #send from another ractor).
|
|
397
|
+
#
|
|
398
|
+
# r = Ractor.new do
|
|
399
|
+
# v1 = Ractor.receive
|
|
400
|
+
# puts "Received: #{v1}"
|
|
401
|
+
# end
|
|
402
|
+
# r.send('message1')
|
|
403
|
+
# r.take
|
|
404
|
+
# # Here will be printed: "Received: message1"
|
|
405
|
+
#
|
|
406
|
+
# Alternatively, the private instance method `receive` may be used:
|
|
407
|
+
#
|
|
408
|
+
# r = Ractor.new do
|
|
409
|
+
# v1 = receive
|
|
410
|
+
# puts "Received: #{v1}"
|
|
411
|
+
# end
|
|
412
|
+
# r.send('message1')
|
|
413
|
+
# r.take
|
|
414
|
+
# # This prints: "Received: message1"
|
|
415
|
+
#
|
|
416
|
+
# The method blocks if the queue is empty.
|
|
417
|
+
#
|
|
418
|
+
# r = Ractor.new do
|
|
419
|
+
# puts "Before first receive"
|
|
420
|
+
# v1 = Ractor.receive
|
|
421
|
+
# puts "Received: #{v1}"
|
|
422
|
+
# v2 = Ractor.receive
|
|
423
|
+
# puts "Received: #{v2}"
|
|
424
|
+
# end
|
|
425
|
+
# wait
|
|
426
|
+
# puts "Still not received"
|
|
427
|
+
# r.send('message1')
|
|
428
|
+
# wait
|
|
429
|
+
# puts "Still received only one"
|
|
430
|
+
# r.send('message2')
|
|
431
|
+
# r.take
|
|
432
|
+
#
|
|
433
|
+
# Output:
|
|
434
|
+
#
|
|
435
|
+
# Before first receive
|
|
436
|
+
# Still not received
|
|
437
|
+
# Received: message1
|
|
438
|
+
# Still received only one
|
|
439
|
+
# Received: message2
|
|
440
|
+
#
|
|
441
|
+
# If close_incoming was called on the ractor, the method raises
|
|
442
|
+
# Ractor::ClosedError if there are no more messages in the incoming queue:
|
|
443
|
+
#
|
|
444
|
+
# Ractor.new do
|
|
445
|
+
# close_incoming
|
|
446
|
+
# receive
|
|
447
|
+
# end
|
|
448
|
+
# wait
|
|
449
|
+
# # in `receive': The incoming port is already closed => #<Ractor:#2 test.rb:1 running> (Ractor::ClosedError)
|
|
350
450
|
#
|
|
351
451
|
def self.receive: () -> untyped
|
|
352
452
|
|
|
353
453
|
# <!--
|
|
354
454
|
# rdoc-file=ractor.rb
|
|
355
|
-
# -
|
|
455
|
+
# - Ractor.receive_if {|msg| block } -> msg
|
|
356
456
|
# -->
|
|
457
|
+
# Receive only a specific message.
|
|
357
458
|
#
|
|
358
|
-
|
|
459
|
+
# Instead of Ractor.receive, Ractor.receive_if can be given a pattern (or any
|
|
460
|
+
# filter) in a block and you can choose the messages to accept that are
|
|
461
|
+
# available in your ractor's incoming queue.
|
|
462
|
+
#
|
|
463
|
+
# r = Ractor.new do
|
|
464
|
+
# p Ractor.receive_if{|msg| msg.match?(/foo/)} #=> "foo3"
|
|
465
|
+
# p Ractor.receive_if{|msg| msg.match?(/bar/)} #=> "bar1"
|
|
466
|
+
# p Ractor.receive_if{|msg| msg.match?(/baz/)} #=> "baz2"
|
|
467
|
+
# end
|
|
468
|
+
# r << "bar1"
|
|
469
|
+
# r << "baz2"
|
|
470
|
+
# r << "foo3"
|
|
471
|
+
# r.take
|
|
472
|
+
#
|
|
473
|
+
# This will output:
|
|
474
|
+
#
|
|
475
|
+
# foo3
|
|
476
|
+
# bar1
|
|
477
|
+
# baz2
|
|
478
|
+
#
|
|
479
|
+
# If the block returns a truthy value, the message is removed from the incoming
|
|
480
|
+
# queue and returned. Otherwise, the message remains in the incoming queue and
|
|
481
|
+
# the next messages are checked by the given block.
|
|
482
|
+
#
|
|
483
|
+
# If there are no messages left in the incoming queue, the method will block
|
|
484
|
+
# until new messages arrive.
|
|
485
|
+
#
|
|
486
|
+
# If the block is escaped by break/return/exception/throw, the message is
|
|
487
|
+
# removed from the incoming queue as if a truthy value had been returned.
|
|
488
|
+
#
|
|
489
|
+
# r = Ractor.new do
|
|
490
|
+
# val = Ractor.receive_if{|msg| msg.is_a?(Array)}
|
|
491
|
+
# puts "Received successfully: #{val}"
|
|
492
|
+
# end
|
|
493
|
+
#
|
|
494
|
+
# r.send(1)
|
|
495
|
+
# r.send('test')
|
|
496
|
+
# wait
|
|
497
|
+
# puts "2 non-matching sent, nothing received"
|
|
498
|
+
# r.send([1, 2, 3])
|
|
499
|
+
# wait
|
|
500
|
+
#
|
|
501
|
+
# Prints:
|
|
502
|
+
#
|
|
503
|
+
# 2 non-matching sent, nothing received
|
|
504
|
+
# Received successfully: [1, 2, 3]
|
|
505
|
+
#
|
|
506
|
+
# Note that you can not call receive/receive_if in the given block recursively.
|
|
507
|
+
# You should not do any tasks in the block other than message filtration.
|
|
508
|
+
#
|
|
509
|
+
# Ractor.current << true
|
|
510
|
+
# Ractor.receive_if{|msg| Ractor.receive}
|
|
511
|
+
# #=> `receive': can not call receive/receive_if recursively (Ractor::Error)
|
|
512
|
+
#
|
|
513
|
+
def self.receive_if: () { (untyped) -> boolish } -> untyped
|
|
359
514
|
|
|
360
515
|
# <!--
|
|
361
516
|
# rdoc-file=ractor.rb
|
|
362
|
-
# -
|
|
517
|
+
# - recv()
|
|
363
518
|
# -->
|
|
364
|
-
# TBD
|
|
365
519
|
#
|
|
366
|
-
|
|
520
|
+
alias self.recv self.receive
|
|
367
521
|
|
|
368
522
|
# <!--
|
|
369
523
|
# rdoc-file=ractor.rb
|
|
370
|
-
# - Ractor.
|
|
524
|
+
# - Ractor.select(*ractors, [yield_value:, move: false]) -> [ractor or symbol, obj]
|
|
371
525
|
# -->
|
|
372
|
-
#
|
|
526
|
+
# Wait for any ractor to have something in its outgoing port, read from this
|
|
527
|
+
# ractor, and then return that ractor and the object received.
|
|
373
528
|
#
|
|
374
|
-
# Ractor.
|
|
375
|
-
# Ractor.
|
|
376
|
-
# Ractor.shareable?('foo'.freeze) #=> true
|
|
529
|
+
# r1 = Ractor.new {Ractor.yield 'from 1'}
|
|
530
|
+
# r2 = Ractor.new {Ractor.yield 'from 2'}
|
|
377
531
|
#
|
|
378
|
-
#
|
|
379
|
-
# docs.
|
|
532
|
+
# r, obj = Ractor.select(r1, r2)
|
|
380
533
|
#
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
#
|
|
384
|
-
#
|
|
385
|
-
#
|
|
386
|
-
#
|
|
387
|
-
#
|
|
388
|
-
#
|
|
534
|
+
# puts "received #{obj.inspect} from #{r.inspect}"
|
|
535
|
+
# # Prints: received "from 1" from #<Ractor:#2 test.rb:1 running>
|
|
536
|
+
# # But could just as well print "from r2" here, either prints could be first.
|
|
537
|
+
#
|
|
538
|
+
# If one of the given ractors is the current ractor, and it is selected, `r`
|
|
539
|
+
# will contain the `:receive` symbol instead of the ractor object.
|
|
540
|
+
#
|
|
541
|
+
# r1 = Ractor.new(Ractor.current) do |main|
|
|
542
|
+
# main.send 'to main'
|
|
543
|
+
# Ractor.yield 'from 1'
|
|
544
|
+
# end
|
|
545
|
+
# r2 = Ractor.new do
|
|
546
|
+
# Ractor.yield 'from 2'
|
|
547
|
+
# end
|
|
548
|
+
#
|
|
549
|
+
# r, obj = Ractor.select(r1, r2, Ractor.current)
|
|
550
|
+
# puts "received #{obj.inspect} from #{r.inspect}"
|
|
551
|
+
# # Could print: received "to main" from :receive
|
|
552
|
+
#
|
|
553
|
+
# If `yield_value` is provided, that value may be yielded if another ractor is
|
|
554
|
+
# calling #take. In this case, the pair `[:yield, nil]` is returned:
|
|
389
555
|
#
|
|
390
|
-
#
|
|
556
|
+
# r1 = Ractor.new(Ractor.current) do |main|
|
|
557
|
+
# puts "Received from main: #{main.take}"
|
|
558
|
+
# end
|
|
559
|
+
#
|
|
560
|
+
# puts "Trying to select"
|
|
561
|
+
# r, obj = Ractor.select(r1, Ractor.current, yield_value: 123)
|
|
562
|
+
# wait
|
|
563
|
+
# puts "Received #{obj.inspect} from #{r.inspect}"
|
|
391
564
|
#
|
|
392
|
-
#
|
|
393
|
-
# Ractor.shareable_proc{ p a }
|
|
394
|
-
# #=> can not isolate a Proc because it accesses outer variables (a). (ArgumentError)
|
|
565
|
+
# This will print:
|
|
395
566
|
#
|
|
396
|
-
#
|
|
567
|
+
# Trying to select
|
|
568
|
+
# Received from main: 123
|
|
569
|
+
# Received nil from :yield
|
|
397
570
|
#
|
|
398
|
-
#
|
|
399
|
-
#
|
|
571
|
+
# `move` boolean flag defines whether yielded value will be copied (default) or
|
|
572
|
+
# moved.
|
|
400
573
|
#
|
|
401
|
-
def self.
|
|
402
|
-
| [T, S] (self: S) { (?) [self: S] -> T } -> ^(?) [self: S] -> T
|
|
574
|
+
def self.select: (*Ractor ractors, ?move: boolish, ?yield_value: untyped) -> [ Ractor | Symbol, untyped ]
|
|
403
575
|
|
|
404
576
|
# <!--
|
|
405
577
|
# rdoc-file=ractor.rb
|
|
406
|
-
# - Ractor.
|
|
578
|
+
# - Ractor.shareable?(obj) -> true | false
|
|
407
579
|
# -->
|
|
408
|
-
#
|
|
580
|
+
# Checks if the object is shareable by ractors.
|
|
409
581
|
#
|
|
410
|
-
|
|
411
|
-
|
|
582
|
+
# Ractor.shareable?(1) #=> true -- numbers and other immutable basic values are frozen
|
|
583
|
+
# Ractor.shareable?('foo') #=> false, unless the string is frozen due to # frozen_string_literal: true
|
|
584
|
+
# Ractor.shareable?('foo'.freeze) #=> true
|
|
585
|
+
#
|
|
586
|
+
# See also the "Shareable and unshareable objects" section in the Ractor class
|
|
587
|
+
# docs.
|
|
588
|
+
#
|
|
589
|
+
def self.shareable?: (untyped obj) -> bool
|
|
412
590
|
|
|
413
591
|
# <!--
|
|
414
592
|
# rdoc-file=ractor.rb
|
|
415
593
|
# - Ractor.store_if_absent(key){ init_block }
|
|
416
594
|
# -->
|
|
417
|
-
# If the
|
|
595
|
+
# If the correponding value is not set, yield a value with init_block and store
|
|
418
596
|
# the value in thread-safe manner. This method returns corresponding stored
|
|
419
597
|
# value.
|
|
420
598
|
#
|
|
@@ -429,7 +607,47 @@ class Ractor
|
|
|
429
607
|
|
|
430
608
|
# <!--
|
|
431
609
|
# rdoc-file=ractor.rb
|
|
432
|
-
# -
|
|
610
|
+
# - Ractor.yield(msg, move: false) -> nil
|
|
611
|
+
# -->
|
|
612
|
+
# Send a message to the current ractor's outgoing port to be accepted by #take.
|
|
613
|
+
#
|
|
614
|
+
# r = Ractor.new {Ractor.yield 'Hello from ractor'}
|
|
615
|
+
# puts r.take
|
|
616
|
+
# # Prints: "Hello from ractor"
|
|
617
|
+
#
|
|
618
|
+
# This method is blocking, and will return only when somebody consumes the sent
|
|
619
|
+
# message.
|
|
620
|
+
#
|
|
621
|
+
# r = Ractor.new do
|
|
622
|
+
# Ractor.yield 'Hello from ractor'
|
|
623
|
+
# puts "Ractor: after yield"
|
|
624
|
+
# end
|
|
625
|
+
# wait
|
|
626
|
+
# puts "Still not taken"
|
|
627
|
+
# puts r.take
|
|
628
|
+
#
|
|
629
|
+
# This will print:
|
|
630
|
+
#
|
|
631
|
+
# Still not taken
|
|
632
|
+
# Hello from ractor
|
|
633
|
+
# Ractor: after yield
|
|
634
|
+
#
|
|
635
|
+
# If the outgoing port was closed with #close_outgoing, the method will raise:
|
|
636
|
+
#
|
|
637
|
+
# r = Ractor.new do
|
|
638
|
+
# close_outgoing
|
|
639
|
+
# Ractor.yield 'Hello from ractor'
|
|
640
|
+
# end
|
|
641
|
+
# wait
|
|
642
|
+
# # `yield': The outgoing-port is already closed (Ractor::ClosedError)
|
|
643
|
+
#
|
|
644
|
+
# The meaning of the `move` argument is the same as for #send.
|
|
645
|
+
#
|
|
646
|
+
def self.yield: (untyped obj, ?move: boolish) -> untyped
|
|
647
|
+
|
|
648
|
+
# <!--
|
|
649
|
+
# rdoc-file=ractor.rb
|
|
650
|
+
# - <<(obj, move: false)
|
|
433
651
|
# -->
|
|
434
652
|
#
|
|
435
653
|
alias << send
|
|
@@ -438,50 +656,58 @@ class Ractor
|
|
|
438
656
|
# rdoc-file=ractor.rb
|
|
439
657
|
# - [](sym)
|
|
440
658
|
# -->
|
|
441
|
-
# get a value from ractor-local storage
|
|
659
|
+
# get a value from ractor-local storage of current Ractor Obsolete and use
|
|
442
660
|
# Ractor.[] instead.
|
|
443
661
|
#
|
|
444
|
-
%a{deprecated: Use Ractor.[] instead}
|
|
445
662
|
def []: (interned sym) -> untyped
|
|
446
663
|
|
|
447
664
|
# <!--
|
|
448
665
|
# rdoc-file=ractor.rb
|
|
449
666
|
# - []=(sym, val)
|
|
450
667
|
# -->
|
|
451
|
-
# set a value in ractor-local storage
|
|
668
|
+
# set a value in ractor-local storage of current Ractor Obsolete and use
|
|
452
669
|
# Ractor.[]= instead.
|
|
453
670
|
#
|
|
454
|
-
%a{deprecated: Use Ractor.[]= instead}
|
|
455
671
|
def []=: [T] (interned sym, T val) -> T
|
|
456
672
|
|
|
457
673
|
# <!--
|
|
458
674
|
# rdoc-file=ractor.rb
|
|
459
|
-
# - ractor.
|
|
675
|
+
# - ractor.close_incoming -> true | false
|
|
460
676
|
# -->
|
|
461
|
-
#
|
|
677
|
+
# Closes the incoming port and returns whether it was already closed. All
|
|
678
|
+
# further attempts to Ractor.receive in the ractor, and #send to the ractor will
|
|
679
|
+
# fail with Ractor::ClosedError.
|
|
680
|
+
#
|
|
681
|
+
# r = Ractor.new {sleep(500)}
|
|
682
|
+
# r.close_incoming #=> false
|
|
683
|
+
# r.close_incoming #=> true
|
|
684
|
+
# r.send('test')
|
|
685
|
+
# # Ractor::ClosedError (The incoming-port is already closed)
|
|
462
686
|
#
|
|
463
|
-
def
|
|
687
|
+
def close_incoming: () -> bool
|
|
464
688
|
|
|
465
689
|
# <!--
|
|
466
690
|
# rdoc-file=ractor.rb
|
|
467
|
-
# -
|
|
691
|
+
# - ractor.close_outgoing -> true | false
|
|
468
692
|
# -->
|
|
693
|
+
# Closes the outgoing port and returns whether it was already closed. All
|
|
694
|
+
# further attempts to Ractor.yield in the ractor, and #take from the ractor will
|
|
695
|
+
# fail with Ractor::ClosedError.
|
|
469
696
|
#
|
|
470
|
-
|
|
697
|
+
# r = Ractor.new {sleep(500)}
|
|
698
|
+
# r.close_outgoing #=> false
|
|
699
|
+
# r.close_outgoing #=> true
|
|
700
|
+
# r.take
|
|
701
|
+
# # Ractor::ClosedError (The outgoing-port is already closed)
|
|
702
|
+
#
|
|
703
|
+
def close_outgoing: () -> bool
|
|
471
704
|
|
|
472
705
|
# <!--
|
|
473
706
|
# rdoc-file=ractor.rb
|
|
474
|
-
# -
|
|
707
|
+
# - inspect()
|
|
475
708
|
# -->
|
|
476
|
-
# Wait for the termination of the Ractor. If the Ractor was aborted (terminated
|
|
477
|
-
# with an exception), Ractor#value is called to raise an exception.
|
|
478
709
|
#
|
|
479
|
-
|
|
480
|
-
#
|
|
481
|
-
# Ractor.new{ raise "foo" }.join
|
|
482
|
-
# #=> raise an exception "foo (RuntimeError)"
|
|
483
|
-
#
|
|
484
|
-
def join: () -> self
|
|
710
|
+
def inspect: () -> String
|
|
485
711
|
|
|
486
712
|
# <!--
|
|
487
713
|
# rdoc-file=ractor.rb
|
|
@@ -493,60 +719,162 @@ class Ractor
|
|
|
493
719
|
|
|
494
720
|
# <!--
|
|
495
721
|
# rdoc-file=ractor.rb
|
|
496
|
-
# - ractor.
|
|
722
|
+
# - ractor.send(msg, move: false) -> self
|
|
497
723
|
# -->
|
|
498
|
-
#
|
|
499
|
-
# received a Symbol object. :exited will be sent if the ractor terminated
|
|
500
|
-
# without an exception. :aborted will be sent if the ractor terminated with a
|
|
501
|
-
# exception.
|
|
724
|
+
# Send a message to a Ractor's incoming queue to be accepted by Ractor.receive.
|
|
502
725
|
#
|
|
503
|
-
# r = Ractor.new
|
|
504
|
-
#
|
|
505
|
-
#
|
|
726
|
+
# r = Ractor.new do
|
|
727
|
+
# value = Ractor.receive
|
|
728
|
+
# puts "Received #{value}"
|
|
729
|
+
# end
|
|
730
|
+
# r.send 'message'
|
|
731
|
+
# # Prints: "Received: message"
|
|
506
732
|
#
|
|
507
|
-
#
|
|
508
|
-
#
|
|
509
|
-
# port.receive #=> :terminated and r is terminated with an exception "foo"
|
|
733
|
+
# The method is non-blocking (will return immediately even if the ractor is not
|
|
734
|
+
# ready to receive anything):
|
|
510
735
|
#
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
#
|
|
514
|
-
#
|
|
515
|
-
#
|
|
516
|
-
#
|
|
517
|
-
#
|
|
736
|
+
# r = Ractor.new {sleep(5)}
|
|
737
|
+
# r.send('test')
|
|
738
|
+
# puts "Sent successfully"
|
|
739
|
+
# # Prints: "Sent successfully" immediately
|
|
740
|
+
#
|
|
741
|
+
# An attempt to send to a ractor which already finished its execution will raise
|
|
742
|
+
# Ractor::ClosedError.
|
|
743
|
+
#
|
|
744
|
+
# r = Ractor.new {}
|
|
745
|
+
# r.take
|
|
746
|
+
# p r
|
|
747
|
+
# # "#<Ractor:#6 (irb):23 terminated>"
|
|
748
|
+
# r.send('test')
|
|
749
|
+
# # Ractor::ClosedError (The incoming-port is already closed)
|
|
750
|
+
#
|
|
751
|
+
# If close_incoming was called on the ractor, the method also raises
|
|
752
|
+
# Ractor::ClosedError.
|
|
753
|
+
#
|
|
754
|
+
# r = Ractor.new do
|
|
755
|
+
# sleep(500)
|
|
756
|
+
# receive
|
|
757
|
+
# end
|
|
758
|
+
# r.close_incoming
|
|
759
|
+
# r.send('test')
|
|
760
|
+
# # Ractor::ClosedError (The incoming-port is already closed)
|
|
761
|
+
# # The error is raised immediately, not when the ractor tries to receive
|
|
762
|
+
#
|
|
763
|
+
# If the `obj` is unshareable, by default it will be copied into the receiving
|
|
764
|
+
# ractor by deep cloning. If `move: true` is passed, the object is *moved* into
|
|
765
|
+
# the receiving ractor and becomes inaccessible to the sender.
|
|
766
|
+
#
|
|
767
|
+
# r = Ractor.new {puts "Received: #{receive}"}
|
|
768
|
+
# msg = 'message'
|
|
769
|
+
# r.send(msg, move: true)
|
|
770
|
+
# r.take
|
|
771
|
+
# p msg
|
|
772
|
+
#
|
|
773
|
+
# This prints:
|
|
774
|
+
#
|
|
775
|
+
# Received: message
|
|
776
|
+
# in `p': undefined method `inspect' for #<Ractor::MovedObject:0x000055c99b9b69b8>
|
|
777
|
+
#
|
|
778
|
+
# All references to the object and its parts will become invalid to the sender.
|
|
779
|
+
#
|
|
780
|
+
# r = Ractor.new {puts "Received: #{receive}"}
|
|
781
|
+
# s = 'message'
|
|
782
|
+
# ary = [s]
|
|
783
|
+
# copy = ary.dup
|
|
784
|
+
# r.send(ary, move: true)
|
|
785
|
+
#
|
|
786
|
+
# s.inspect
|
|
787
|
+
# # Ractor::MovedError (can not send any methods to a moved object)
|
|
788
|
+
# ary.class
|
|
789
|
+
# # Ractor::MovedError (can not send any methods to a moved object)
|
|
790
|
+
# copy.class
|
|
791
|
+
# # => Array, it is different object
|
|
792
|
+
# copy[0].inspect
|
|
793
|
+
# # Ractor::MovedError (can not send any methods to a moved object)
|
|
794
|
+
# # ...but its item was still a reference to `s`, which was moved
|
|
795
|
+
#
|
|
796
|
+
# If the object is shareable, `move: true` has no effect on it:
|
|
797
|
+
#
|
|
798
|
+
# r = Ractor.new {puts "Received: #{receive}"}
|
|
799
|
+
# s = 'message'.freeze
|
|
800
|
+
# r.send(s, move: true)
|
|
801
|
+
# s.inspect #=> "message", still available
|
|
518
802
|
#
|
|
519
803
|
def send: (untyped obj, ?move: boolish) -> Ractor
|
|
520
804
|
|
|
521
805
|
# <!--
|
|
522
806
|
# rdoc-file=ractor.rb
|
|
523
|
-
# -
|
|
807
|
+
# - ractor.take -> msg
|
|
524
808
|
# -->
|
|
809
|
+
# Get a message from the ractor's outgoing port, which was put there by
|
|
810
|
+
# Ractor.yield or at ractor's termination.
|
|
525
811
|
#
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
#
|
|
529
|
-
#
|
|
530
|
-
#
|
|
531
|
-
#
|
|
532
|
-
#
|
|
812
|
+
# r = Ractor.new do
|
|
813
|
+
# Ractor.yield 'explicit yield'
|
|
814
|
+
# 'last value'
|
|
815
|
+
# end
|
|
816
|
+
# puts r.take #=> 'explicit yield'
|
|
817
|
+
# puts r.take #=> 'last value'
|
|
818
|
+
# puts r.take # Ractor::ClosedError (The outgoing-port is already closed)
|
|
819
|
+
#
|
|
820
|
+
# The fact that the last value is also sent to the outgoing port means that
|
|
821
|
+
# `take` can be used as an analog of Thread#join ("just wait until ractor
|
|
822
|
+
# finishes"). However, it will raise if somebody has already consumed that
|
|
823
|
+
# message.
|
|
824
|
+
#
|
|
825
|
+
# If the outgoing port was closed with #close_outgoing, the method will raise
|
|
826
|
+
# Ractor::ClosedError.
|
|
533
827
|
#
|
|
534
|
-
|
|
828
|
+
# r = Ractor.new do
|
|
829
|
+
# sleep(500)
|
|
830
|
+
# Ractor.yield 'Hello from ractor'
|
|
831
|
+
# end
|
|
832
|
+
# r.close_outgoing
|
|
833
|
+
# r.take
|
|
834
|
+
# # Ractor::ClosedError (The outgoing-port is already closed)
|
|
835
|
+
# # The error would be raised immediately, not when ractor will try to receive
|
|
836
|
+
#
|
|
837
|
+
# If an uncaught exception is raised in the Ractor, it is propagated by take as
|
|
838
|
+
# a Ractor::RemoteError.
|
|
839
|
+
#
|
|
840
|
+
# r = Ractor.new {raise "Something weird happened"}
|
|
841
|
+
#
|
|
842
|
+
# begin
|
|
843
|
+
# r.take
|
|
844
|
+
# rescue => e
|
|
845
|
+
# p e # => #<Ractor::RemoteError: thrown by remote Ractor.>
|
|
846
|
+
# p e.ractor == r # => true
|
|
847
|
+
# p e.cause # => #<RuntimeError: Something weird happened>
|
|
848
|
+
# end
|
|
849
|
+
#
|
|
850
|
+
# Ractor::ClosedError is a descendant of StopIteration, so the termination of
|
|
851
|
+
# the ractor will break out of any loops that receive this message without
|
|
852
|
+
# propagating the error:
|
|
853
|
+
#
|
|
854
|
+
# r = Ractor.new do
|
|
855
|
+
# 3.times {|i| Ractor.yield "message #{i}"}
|
|
856
|
+
# "finishing"
|
|
857
|
+
# end
|
|
858
|
+
#
|
|
859
|
+
# loop {puts "Received: " + r.take}
|
|
860
|
+
# puts "Continue successfully"
|
|
861
|
+
#
|
|
862
|
+
# This will print:
|
|
863
|
+
#
|
|
864
|
+
# Received: message 0
|
|
865
|
+
# Received: message 1
|
|
866
|
+
# Received: message 2
|
|
867
|
+
# Received: finishing
|
|
868
|
+
# Continue successfully
|
|
869
|
+
#
|
|
870
|
+
def take: () -> untyped
|
|
535
871
|
|
|
536
872
|
# <!--
|
|
537
873
|
# rdoc-file=ractor.rb
|
|
538
|
-
# -
|
|
874
|
+
# - to_s()
|
|
539
875
|
# -->
|
|
540
|
-
# Waits for `ractor` to complete, using #join, and return its value or raise the
|
|
541
|
-
# exception which terminated the Ractor. The value will not be copied even if it
|
|
542
|
-
# is unshareable object. Therefore at most 1 Ractor can get a value.
|
|
543
|
-
#
|
|
544
|
-
# r = Ractor.new{ [1, 2] }
|
|
545
|
-
# r.value #=> [1, 2] (unshareable object)
|
|
546
|
-
#
|
|
547
|
-
# Ractor.new(r){|r| r.value} #=> Ractor::Error
|
|
548
876
|
#
|
|
549
|
-
|
|
877
|
+
alias to_s inspect
|
|
550
878
|
|
|
551
879
|
private
|
|
552
880
|
|
|
@@ -610,15 +938,9 @@ class Ractor
|
|
|
610
938
|
class ClosedError < StopIteration
|
|
611
939
|
end
|
|
612
940
|
|
|
613
|
-
# <!-- rdoc-file=ractor.c -->
|
|
614
|
-
# The parent class of Ractor-related error classes.
|
|
615
|
-
#
|
|
616
941
|
class Error < RuntimeError
|
|
617
942
|
end
|
|
618
943
|
|
|
619
|
-
# <!-- rdoc-file=ractor.c -->
|
|
620
|
-
# Raised on attempt to make a Ractor-unshareable object Ractor-shareable.
|
|
621
|
-
#
|
|
622
944
|
class IsolationError < Ractor::Error
|
|
623
945
|
end
|
|
624
946
|
|
|
@@ -715,166 +1037,6 @@ class Ractor
|
|
|
715
1037
|
def method_missing: (*untyped) -> untyped
|
|
716
1038
|
end
|
|
717
1039
|
|
|
718
|
-
# <!-- rdoc-file=ractor.rb -->
|
|
719
|
-
# Port objects transmit messages between Ractors.
|
|
720
|
-
#
|
|
721
|
-
class Port[T = untyped]
|
|
722
|
-
# <!--
|
|
723
|
-
# rdoc-file=ractor.rb
|
|
724
|
-
# - <<(obj, move: false)
|
|
725
|
-
# -->
|
|
726
|
-
#
|
|
727
|
-
alias << send
|
|
728
|
-
|
|
729
|
-
# <!--
|
|
730
|
-
# rdoc-file=ractor.rb
|
|
731
|
-
# - port.close
|
|
732
|
-
# -->
|
|
733
|
-
# Close the port. On the closed port, sending is not prohibited. Receiving is
|
|
734
|
-
# also not allowed if there is no sent messages arrived before closing.
|
|
735
|
-
#
|
|
736
|
-
# port = Ractor::Port.new
|
|
737
|
-
# Ractor.new port do |port|
|
|
738
|
-
# port.send 1 # OK
|
|
739
|
-
# port.send 2 # OK
|
|
740
|
-
# port.close
|
|
741
|
-
# port.send 3 # raise Ractor::ClosedError
|
|
742
|
-
# end
|
|
743
|
-
#
|
|
744
|
-
# port.receive #=> 1
|
|
745
|
-
# port.receive #=> 2
|
|
746
|
-
# port.receive #=> raise Ractor::ClosedError
|
|
747
|
-
#
|
|
748
|
-
# Now, only a Ractor which creates the port is allowed to close ports.
|
|
749
|
-
#
|
|
750
|
-
# port = Ractor::Port.new
|
|
751
|
-
# Ractor.new port do |port|
|
|
752
|
-
# port.close #=> closing port by other ractors is not allowed (Ractor::Error)
|
|
753
|
-
# end.join
|
|
754
|
-
#
|
|
755
|
-
def close: () -> void
|
|
756
|
-
|
|
757
|
-
# <!--
|
|
758
|
-
# rdoc-file=ractor.rb
|
|
759
|
-
# - port.closed? -> true/false
|
|
760
|
-
# -->
|
|
761
|
-
# Return the port is closed or not.
|
|
762
|
-
#
|
|
763
|
-
def closed?: () -> bool
|
|
764
|
-
|
|
765
|
-
# <!--
|
|
766
|
-
# rdoc-file=ractor.rb
|
|
767
|
-
# - port.inspect -> string
|
|
768
|
-
# -->
|
|
769
|
-
#
|
|
770
|
-
def inspect: () -> String
|
|
771
|
-
|
|
772
|
-
# <!--
|
|
773
|
-
# rdoc-file=ractor.rb
|
|
774
|
-
# - port.receive -> msg
|
|
775
|
-
# -->
|
|
776
|
-
# Receive a message to the port (which was sent there by Port#send).
|
|
777
|
-
#
|
|
778
|
-
# port = Ractor::Port.new
|
|
779
|
-
# r = Ractor.new port do |port|
|
|
780
|
-
# port.send('message1')
|
|
781
|
-
# end
|
|
782
|
-
#
|
|
783
|
-
# v1 = port.receive
|
|
784
|
-
# puts "Received: #{v1}"
|
|
785
|
-
# r.join
|
|
786
|
-
# # Here will be printed: "Received: message1"
|
|
787
|
-
#
|
|
788
|
-
# The method blocks if the message queue is empty.
|
|
789
|
-
#
|
|
790
|
-
# port = Ractor::Port.new
|
|
791
|
-
# r = Ractor.new port do |port|
|
|
792
|
-
# wait
|
|
793
|
-
# puts "Still not received"
|
|
794
|
-
# port.send('message1')
|
|
795
|
-
# wait
|
|
796
|
-
# puts "Still received only one"
|
|
797
|
-
# port.send('message2')
|
|
798
|
-
# end
|
|
799
|
-
# puts "Before first receive"
|
|
800
|
-
# v1 = port.receive
|
|
801
|
-
# puts "Received: #{v1}"
|
|
802
|
-
# v2 = port.receive
|
|
803
|
-
# puts "Received: #{v2}"
|
|
804
|
-
# r.join
|
|
805
|
-
#
|
|
806
|
-
# Output:
|
|
807
|
-
#
|
|
808
|
-
# Before first receive
|
|
809
|
-
# Still not received
|
|
810
|
-
# Received: message1
|
|
811
|
-
# Still received only one
|
|
812
|
-
# Received: message2
|
|
813
|
-
#
|
|
814
|
-
# If close_incoming was called on the ractor, the method raises
|
|
815
|
-
# Ractor::ClosedError if there are no more messages in the message queue:
|
|
816
|
-
#
|
|
817
|
-
# port = Ractor::Port.new
|
|
818
|
-
# port.close
|
|
819
|
-
# port.receive #=> raise Ractor::ClosedError
|
|
820
|
-
#
|
|
821
|
-
def receive: () -> T
|
|
822
|
-
|
|
823
|
-
# <!--
|
|
824
|
-
# rdoc-file=ractor.rb
|
|
825
|
-
# - port.send(msg, move: false) -> self
|
|
826
|
-
# -->
|
|
827
|
-
# Send a message to a port to be accepted by port.receive.
|
|
828
|
-
#
|
|
829
|
-
# port = Ractor::Port.new
|
|
830
|
-
# r = Ractor.new do
|
|
831
|
-
# r.send 'message'
|
|
832
|
-
# end
|
|
833
|
-
# value = port.receive
|
|
834
|
-
# puts "Received #{value}"
|
|
835
|
-
# # Prints: "Received: message"
|
|
836
|
-
#
|
|
837
|
-
# The method is non-blocking (will return immediately even if the ractor is not
|
|
838
|
-
# ready to receive anything):
|
|
839
|
-
#
|
|
840
|
-
# port = Ractor::Port.new
|
|
841
|
-
# r = Ractor.new(port) do |port|
|
|
842
|
-
# port.send 'test'}
|
|
843
|
-
# puts "Sent successfully"
|
|
844
|
-
# # Prints: "Sent successfully" immediately
|
|
845
|
-
# end
|
|
846
|
-
#
|
|
847
|
-
# An attempt to send to a port which already closed its execution will raise
|
|
848
|
-
# Ractor::ClosedError.
|
|
849
|
-
#
|
|
850
|
-
# r = Ractor.new {Ractor::Port.new}
|
|
851
|
-
# r.join
|
|
852
|
-
# p r
|
|
853
|
-
# # "#<Ractor:#6 (irb):23 terminated>"
|
|
854
|
-
# port = r.value
|
|
855
|
-
# port.send('test') # raise Ractor::ClosedError
|
|
856
|
-
#
|
|
857
|
-
# If the `obj` is unshareable, by default it will be copied into the receiving
|
|
858
|
-
# ractor by deep cloning.
|
|
859
|
-
#
|
|
860
|
-
# If the object is shareable, it only send a reference to the object without
|
|
861
|
-
# cloning.
|
|
862
|
-
#
|
|
863
|
-
def send: (T obj, ?move: boolish) -> self
|
|
864
|
-
|
|
865
|
-
private
|
|
866
|
-
|
|
867
|
-
# <!--
|
|
868
|
-
# rdoc-file=ractor_sync.c
|
|
869
|
-
# - Ractor::Port.new -> new_port
|
|
870
|
-
# -->
|
|
871
|
-
# Returns a new Ractor::Port object.
|
|
872
|
-
#
|
|
873
|
-
def initialize: () -> void
|
|
874
|
-
|
|
875
|
-
def initialize_copy: (untyped) -> untyped
|
|
876
|
-
end
|
|
877
|
-
|
|
878
1040
|
# <!-- rdoc-file=ractor.c -->
|
|
879
1041
|
# Raised on attempt to Ractor#take if there was an uncaught exception in the
|
|
880
1042
|
# Ractor. Its `cause` will contain the original exception, and `ractor` is the
|
|
@@ -897,9 +1059,6 @@ class Ractor
|
|
|
897
1059
|
def ractor: () -> Ractor
|
|
898
1060
|
end
|
|
899
1061
|
|
|
900
|
-
# <!-- rdoc-file=ractor.c -->
|
|
901
|
-
# Raised when Ractor-unsafe C-methods is invoked by a non-main Ractor.
|
|
902
|
-
#
|
|
903
1062
|
class UnsafeError < Ractor::Error
|
|
904
1063
|
end
|
|
905
1064
|
|