rbs 3.9.5 → 3.10.0.pre.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/.clang-format +74 -0
- data/.clangd +2 -0
- data/.github/workflows/c-check.yml +54 -0
- data/.github/workflows/comments.yml +3 -3
- data/.github/workflows/ruby.yml +34 -19
- data/.github/workflows/typecheck.yml +1 -1
- data/.github/workflows/windows.yml +1 -1
- data/.gitignore +4 -0
- data/README.md +38 -1
- data/Rakefile +152 -23
- data/config.yml +190 -62
- data/core/array.rbs +44 -43
- data/core/dir.rbs +2 -2
- data/core/encoding.rbs +3 -2
- data/core/enumerable.rbs +89 -2
- data/core/errno.rbs +8 -0
- data/core/errors.rbs +28 -1
- data/core/exception.rbs +2 -2
- data/core/fiber.rbs +3 -3
- data/core/file.rbs +26 -11
- data/core/float.rbs +1 -1
- data/core/gc.rbs +422 -281
- data/core/hash.rbs +1024 -727
- data/core/io/wait.rbs +11 -33
- data/core/io.rbs +6 -4
- data/core/kernel.rbs +49 -43
- data/core/marshal.rbs +1 -1
- data/core/match_data.rbs +1 -1
- data/core/math.rbs +42 -3
- data/core/method.rbs +14 -6
- data/core/module.rbs +71 -11
- data/core/nil_class.rbs +3 -3
- data/core/numeric.rbs +8 -8
- data/core/object.rbs +3 -3
- data/core/object_space.rbs +13 -0
- data/{stdlib/pathname/0 → core}/pathname.rbs +253 -352
- data/core/proc.rbs +15 -8
- data/core/process.rbs +2 -2
- data/core/ractor.rbs +278 -437
- data/core/range.rbs +6 -7
- data/core/rbs/unnamed/argf.rbs +1 -1
- data/core/rbs/unnamed/env_class.rbs +1 -1
- data/core/rbs/unnamed/random.rbs +4 -2
- data/core/regexp.rbs +22 -17
- data/core/ruby_vm.rbs +6 -4
- data/core/rubygems/errors.rbs +3 -70
- data/core/rubygems/rubygems.rbs +11 -79
- data/core/set.rbs +439 -332
- data/core/string.rbs +2897 -1117
- data/core/struct.rbs +1 -1
- data/core/symbol.rbs +4 -4
- data/core/thread.rbs +83 -20
- data/core/time.rbs +35 -9
- data/core/unbound_method.rbs +14 -6
- data/docs/aliases.md +79 -0
- data/docs/collection.md +2 -2
- data/docs/gem.md +0 -1
- data/docs/sigs.md +3 -3
- data/ext/rbs_extension/ast_translation.c +1016 -0
- data/ext/rbs_extension/ast_translation.h +37 -0
- data/ext/rbs_extension/class_constants.c +157 -0
- data/{include/rbs/constants.h → ext/rbs_extension/class_constants.h} +7 -1
- data/ext/rbs_extension/compat.h +10 -0
- data/ext/rbs_extension/extconf.rb +25 -1
- data/ext/rbs_extension/legacy_location.c +317 -0
- data/ext/rbs_extension/legacy_location.h +45 -0
- data/ext/rbs_extension/main.c +365 -14
- data/ext/rbs_extension/rbs_extension.h +6 -21
- data/ext/rbs_extension/rbs_string_bridging.c +9 -0
- data/ext/rbs_extension/rbs_string_bridging.h +24 -0
- data/include/rbs/ast.h +687 -0
- data/include/rbs/defines.h +86 -0
- data/include/rbs/lexer.h +199 -0
- data/include/rbs/location.h +59 -0
- data/include/rbs/parser.h +135 -0
- data/include/rbs/string.h +49 -0
- data/include/rbs/util/rbs_allocator.h +59 -0
- data/include/rbs/util/rbs_assert.h +20 -0
- data/include/rbs/util/rbs_buffer.h +83 -0
- data/include/rbs/util/rbs_constant_pool.h +6 -67
- data/include/rbs/util/rbs_encoding.h +282 -0
- data/include/rbs/util/rbs_unescape.h +23 -0
- data/include/rbs.h +1 -2
- data/lib/rbs/annotate/formatter.rb +3 -13
- data/lib/rbs/annotate/rdoc_annotator.rb +3 -1
- data/lib/rbs/annotate/rdoc_source.rb +1 -1
- data/lib/rbs/cli/validate.rb +2 -2
- data/lib/rbs/cli.rb +1 -1
- data/lib/rbs/collection/config/lockfile_generator.rb +1 -0
- data/lib/rbs/definition_builder/ancestor_builder.rb +5 -5
- data/lib/rbs/environment.rb +64 -59
- data/lib/rbs/environment_loader.rb +1 -1
- data/lib/rbs/errors.rb +1 -1
- data/lib/rbs/parser_aux.rb +5 -0
- data/lib/rbs/resolver/constant_resolver.rb +2 -2
- data/lib/rbs/resolver/type_name_resolver.rb +124 -38
- data/lib/rbs/test/type_check.rb +13 -0
- data/lib/rbs/types.rb +3 -1
- data/lib/rbs/version.rb +1 -1
- data/lib/rbs.rb +1 -1
- data/lib/rdoc/discover.rb +1 -1
- data/lib/rdoc_plugin/parser.rb +3 -3
- data/sig/annotate/formatter.rbs +2 -2
- data/sig/annotate/rdoc_annotater.rbs +1 -1
- data/sig/environment.rbs +57 -6
- data/sig/manifest.yaml +0 -1
- data/sig/parser.rbs +20 -0
- data/sig/resolver/type_name_resolver.rbs +38 -7
- data/sig/types.rbs +4 -1
- data/src/ast.c +1256 -0
- data/src/lexer.c +2956 -0
- data/src/lexer.re +147 -0
- data/src/lexstate.c +205 -0
- data/src/location.c +71 -0
- data/src/parser.c +3495 -0
- data/src/string.c +90 -0
- data/src/util/rbs_allocator.c +152 -0
- data/src/util/rbs_assert.c +21 -0
- data/src/util/rbs_buffer.c +54 -0
- data/src/util/rbs_constant_pool.c +16 -86
- data/src/util/rbs_encoding.c +21308 -0
- data/src/util/rbs_unescape.c +131 -0
- data/stdlib/cgi/0/core.rbs +2 -396
- data/stdlib/cgi/0/manifest.yaml +1 -0
- data/stdlib/cgi-escape/0/escape.rbs +153 -0
- data/stdlib/coverage/0/coverage.rbs +3 -1
- data/stdlib/delegate/0/delegator.rbs +10 -7
- data/stdlib/erb/0/erb.rbs +737 -347
- data/stdlib/fileutils/0/fileutils.rbs +18 -13
- data/stdlib/forwardable/0/forwardable.rbs +3 -0
- data/stdlib/json/0/json.rbs +67 -48
- data/stdlib/net-http/0/net-http.rbs +3 -0
- data/stdlib/objspace/0/objspace.rbs +8 -3
- data/stdlib/open-uri/0/open-uri.rbs +40 -0
- data/stdlib/openssl/0/openssl.rbs +182 -149
- data/stdlib/optparse/0/optparse.rbs +3 -3
- data/stdlib/rdoc/0/code_object.rbs +2 -2
- data/stdlib/rdoc/0/comment.rbs +2 -0
- data/stdlib/rdoc/0/options.rbs +76 -0
- data/stdlib/rdoc/0/rdoc.rbs +7 -5
- data/stdlib/rdoc/0/store.rbs +1 -1
- data/stdlib/resolv/0/resolv.rbs +25 -68
- data/stdlib/ripper/0/ripper.rbs +5 -2
- data/stdlib/singleton/0/singleton.rbs +3 -0
- data/stdlib/socket/0/socket.rbs +13 -1
- data/stdlib/socket/0/tcp_socket.rbs +10 -2
- data/stdlib/stringio/0/stringio.rbs +412 -80
- data/stdlib/strscan/0/string_scanner.rbs +31 -31
- data/stdlib/tempfile/0/tempfile.rbs +1 -1
- data/stdlib/tsort/0/cyclic.rbs +3 -0
- data/stdlib/uri/0/common.rbs +11 -2
- data/stdlib/uri/0/file.rbs +1 -1
- data/stdlib/uri/0/generic.rbs +16 -15
- data/stdlib/uri/0/rfc2396_parser.rbs +6 -7
- data/stdlib/zlib/0/zstream.rbs +1 -0
- metadata +41 -18
- data/ext/rbs_extension/lexer.c +0 -2728
- data/ext/rbs_extension/lexer.h +0 -179
- data/ext/rbs_extension/lexer.re +0 -147
- data/ext/rbs_extension/lexstate.c +0 -175
- data/ext/rbs_extension/location.c +0 -325
- data/ext/rbs_extension/location.h +0 -85
- data/ext/rbs_extension/parser.c +0 -2982
- data/ext/rbs_extension/parser.h +0 -18
- data/ext/rbs_extension/parserstate.c +0 -411
- data/ext/rbs_extension/parserstate.h +0 -163
- data/ext/rbs_extension/unescape.c +0 -32
- data/include/rbs/ruby_objs.h +0 -72
- data/src/constants.c +0 -153
- data/src/ruby_objs.c +0 -799
data/core/ractor.rbs
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
# <!-- rdoc-file=ractor.rb -->
|
|
2
|
-
# Ractor is an Actor-model abstraction for Ruby that provides thread-safe
|
|
3
|
-
# parallel execution.
|
|
4
|
-
#
|
|
5
2
|
# Ractor.new makes a new Ractor, which can run in parallel.
|
|
6
3
|
#
|
|
7
4
|
# # The simplest ractor
|
|
8
5
|
# r = Ractor.new {puts "I am in Ractor!"}
|
|
9
|
-
# r.
|
|
6
|
+
# r.join # wait for it to finish
|
|
10
7
|
# # Here, "I am in Ractor!" is printed
|
|
11
8
|
#
|
|
12
9
|
# Ractors do not share all objects with each other. There are two main benefits
|
|
@@ -40,55 +37,12 @@
|
|
|
40
37
|
# puts "I am in Ractor! a=#{a_in_ractor}"
|
|
41
38
|
# end
|
|
42
39
|
# r.send(a) # pass it
|
|
43
|
-
# r.
|
|
40
|
+
# r.join
|
|
44
41
|
# # Here, "I am in Ractor! a=1" is printed
|
|
45
42
|
#
|
|
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
|
-
#
|
|
53
43
|
# In addition to that, any arguments passed to Ractor.new are passed to the
|
|
54
44
|
# block and available there as if received by Ractor.receive, and the last block
|
|
55
|
-
# value
|
|
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.
|
|
45
|
+
# value can be received with Ractor#value.
|
|
92
46
|
#
|
|
93
47
|
# ## Shareable and unshareable objects
|
|
94
48
|
#
|
|
@@ -128,7 +82,7 @@
|
|
|
128
82
|
# puts "In ractor: #{data2.object_id}, #{data2[0].object_id}, #{data2[1].object_id}"
|
|
129
83
|
# end
|
|
130
84
|
# r.send(data)
|
|
131
|
-
# r.
|
|
85
|
+
# r.join
|
|
132
86
|
# puts "Outside : #{data.object_id}, #{data[0].object_id}, #{data[1].object_id}"
|
|
133
87
|
#
|
|
134
88
|
# This will output something like:
|
|
@@ -151,7 +105,7 @@
|
|
|
151
105
|
# puts "In ractor: #{data_in_ractor.object_id}, #{data_in_ractor[0].object_id}"
|
|
152
106
|
# end
|
|
153
107
|
# r.send(data, move: true)
|
|
154
|
-
# r.
|
|
108
|
+
# r.join
|
|
155
109
|
# puts "Outside: moved? #{Ractor::MovedObject === data}"
|
|
156
110
|
# puts "Outside: #{data.inspect}"
|
|
157
111
|
#
|
|
@@ -164,7 +118,7 @@
|
|
|
164
118
|
# Notice that even `inspect` (and more basic methods like `__id__`) is
|
|
165
119
|
# inaccessible on a moved object.
|
|
166
120
|
#
|
|
167
|
-
# Class and Module objects are shareable so the class/module definitions are
|
|
121
|
+
# `Class` and `Module` objects are shareable so the class/module definitions are
|
|
168
122
|
# shared between ractors. Ractor objects are also shareable. All operations on
|
|
169
123
|
# shareable objects are thread-safe, so the thread-safety property will be kept.
|
|
170
124
|
# We can not define mutable shareable objects in Ruby, but C extensions can
|
|
@@ -189,7 +143,7 @@
|
|
|
189
143
|
# puts "I can't see #{cls.tricky}"
|
|
190
144
|
# cls.tricky = true # doesn't get here, but this would also raise an error
|
|
191
145
|
# end
|
|
192
|
-
# r.
|
|
146
|
+
# r.join
|
|
193
147
|
# # I see C
|
|
194
148
|
# # can not access instance variables of classes/modules from non-main Ractors (RuntimeError)
|
|
195
149
|
#
|
|
@@ -203,7 +157,7 @@
|
|
|
203
157
|
# puts "GOOD=#{GOOD}"
|
|
204
158
|
# puts "BAD=#{BAD}"
|
|
205
159
|
# end
|
|
206
|
-
# r.
|
|
160
|
+
# r.join
|
|
207
161
|
# # GOOD=good
|
|
208
162
|
# # can not access non-shareable objects in constant Object::BAD by non-main Ractor. (NameError)
|
|
209
163
|
#
|
|
@@ -213,7 +167,7 @@
|
|
|
213
167
|
# puts "I see #{C}"
|
|
214
168
|
# puts "I can't see #{C.tricky}"
|
|
215
169
|
# end
|
|
216
|
-
# r.
|
|
170
|
+
# r.join
|
|
217
171
|
# # I see C
|
|
218
172
|
# # can not access instance variables of classes/modules from non-main Ractors (RuntimeError)
|
|
219
173
|
#
|
|
@@ -229,7 +183,7 @@
|
|
|
229
183
|
# a = 1
|
|
230
184
|
# Thread.new {puts "Thread in ractor: a=#{a}"}.join
|
|
231
185
|
# end
|
|
232
|
-
# r.
|
|
186
|
+
# r.join
|
|
233
187
|
# # Here "Thread in ractor: a=1" will be printed
|
|
234
188
|
#
|
|
235
189
|
# ## Note on code examples
|
|
@@ -242,7 +196,7 @@
|
|
|
242
196
|
# end
|
|
243
197
|
#
|
|
244
198
|
# It is **only for demonstration purposes** and shouldn't be used in a real
|
|
245
|
-
# code. Most of the time, #
|
|
199
|
+
# code. Most of the time, #join is used to wait for ractors to finish.
|
|
246
200
|
#
|
|
247
201
|
# ## Reference
|
|
248
202
|
#
|
|
@@ -280,10 +234,10 @@ class Ractor
|
|
|
280
234
|
# Returns the number of Ractors currently running or blocking (waiting).
|
|
281
235
|
#
|
|
282
236
|
# Ractor.count #=> 1
|
|
283
|
-
# r = Ractor.new(name: 'example') { Ractor.
|
|
237
|
+
# r = Ractor.new(name: 'example') { Ractor.receive }
|
|
284
238
|
# Ractor.count #=> 2 (main + example ractor)
|
|
285
|
-
# r
|
|
286
|
-
# r.
|
|
239
|
+
# r << 42 # r's Ractor.receive will resume
|
|
240
|
+
# r.join # wait for r's termination
|
|
287
241
|
# Ractor.count #=> 1
|
|
288
242
|
#
|
|
289
243
|
def self.count: () -> Integer
|
|
@@ -363,7 +317,7 @@ class Ractor
|
|
|
363
317
|
# `self` inside the block will refer to the current Ractor.
|
|
364
318
|
#
|
|
365
319
|
# r = Ractor.new { puts "Hi, I am #{self.inspect}" }
|
|
366
|
-
# r.
|
|
320
|
+
# r.join
|
|
367
321
|
# # Prints "Hi, I am #<Ractor:#2 test.rb:1 running>"
|
|
368
322
|
#
|
|
369
323
|
# Any `args` passed are propagated to the block arguments by the same rules as
|
|
@@ -375,14 +329,14 @@ class Ractor
|
|
|
375
329
|
# r = Ractor.new(arg) {|received_arg|
|
|
376
330
|
# puts "Received: #{received_arg} (##{received_arg.object_id})"
|
|
377
331
|
# }
|
|
378
|
-
# r.
|
|
332
|
+
# r.join
|
|
379
333
|
# # Prints:
|
|
380
334
|
# # Passing: [1, 2, 3] (#280)
|
|
381
335
|
# # Received: [1, 2, 3] (#300)
|
|
382
336
|
#
|
|
383
337
|
# Ractor's `name` can be set for debugging purposes:
|
|
384
338
|
#
|
|
385
|
-
# r = Ractor.new(name: 'my ractor') {}; r.
|
|
339
|
+
# r = Ractor.new(name: 'my ractor') {}; r.join
|
|
386
340
|
# p r
|
|
387
341
|
# #=> #<Ractor:#3 my ractor test.rb:1 terminated>
|
|
388
342
|
#
|
|
@@ -390,128 +344,12 @@ class Ractor
|
|
|
390
344
|
|
|
391
345
|
# <!--
|
|
392
346
|
# rdoc-file=ractor.rb
|
|
393
|
-
# - Ractor.receive ->
|
|
347
|
+
# - Ractor.receive -> obj
|
|
394
348
|
# -->
|
|
395
|
-
# Receive a message from the
|
|
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)
|
|
349
|
+
# Receive a message from the default port.
|
|
450
350
|
#
|
|
451
351
|
def self.receive: () -> untyped
|
|
452
352
|
|
|
453
|
-
# <!--
|
|
454
|
-
# rdoc-file=ractor.rb
|
|
455
|
-
# - Ractor.receive_if {|msg| block } -> msg
|
|
456
|
-
# -->
|
|
457
|
-
# Receive only a specific message.
|
|
458
|
-
#
|
|
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
|
|
514
|
-
|
|
515
353
|
# <!--
|
|
516
354
|
# rdoc-file=ractor.rb
|
|
517
355
|
# - recv()
|
|
@@ -521,57 +359,11 @@ class Ractor
|
|
|
521
359
|
|
|
522
360
|
# <!--
|
|
523
361
|
# rdoc-file=ractor.rb
|
|
524
|
-
# - Ractor.select(*
|
|
362
|
+
# - Ractor.select(*ports) -> [...]
|
|
525
363
|
# -->
|
|
526
|
-
#
|
|
527
|
-
# ractor, and then return that ractor and the object received.
|
|
528
|
-
#
|
|
529
|
-
# r1 = Ractor.new {Ractor.yield 'from 1'}
|
|
530
|
-
# r2 = Ractor.new {Ractor.yield 'from 2'}
|
|
531
|
-
#
|
|
532
|
-
# r, obj = Ractor.select(r1, r2)
|
|
364
|
+
# TBD
|
|
533
365
|
#
|
|
534
|
-
|
|
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:
|
|
555
|
-
#
|
|
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}"
|
|
564
|
-
#
|
|
565
|
-
# This will print:
|
|
566
|
-
#
|
|
567
|
-
# Trying to select
|
|
568
|
-
# Received from main: 123
|
|
569
|
-
# Received nil from :yield
|
|
570
|
-
#
|
|
571
|
-
# `move` boolean flag defines whether yielded value will be copied (default) or
|
|
572
|
-
# moved.
|
|
573
|
-
#
|
|
574
|
-
def self.select: (*Ractor ractors, ?move: boolish, ?yield_value: untyped) -> [ Ractor | Symbol, untyped ]
|
|
366
|
+
def self.select: (?) -> Array[untyped]
|
|
575
367
|
|
|
576
368
|
# <!--
|
|
577
369
|
# rdoc-file=ractor.rb
|
|
@@ -588,11 +380,41 @@ class Ractor
|
|
|
588
380
|
#
|
|
589
381
|
def self.shareable?: (untyped obj) -> bool
|
|
590
382
|
|
|
383
|
+
# <!--
|
|
384
|
+
# rdoc-file=ractor.rb
|
|
385
|
+
# - Ractor.sharable_proc(self: nil){} -> sharable proc
|
|
386
|
+
# -->
|
|
387
|
+
# It returns shareable Proc object. The Proc object is shareable and the self in
|
|
388
|
+
# a block will be replaced with the value passed via `self:` keyword.
|
|
389
|
+
#
|
|
390
|
+
# In a shareable Proc, you can not access to the outer variables.
|
|
391
|
+
#
|
|
392
|
+
# a = 42
|
|
393
|
+
# Ractor.shareable_proc{ p a }
|
|
394
|
+
# #=> can not isolate a Proc because it accesses outer variables (a). (ArgumentError)
|
|
395
|
+
#
|
|
396
|
+
# The `self` should be a sharable object
|
|
397
|
+
#
|
|
398
|
+
# Ractor.shareable_proc(self: self){}
|
|
399
|
+
# #=> self should be shareable: main (Ractor::IsolationError)
|
|
400
|
+
#
|
|
401
|
+
def self.shareable_proc: [T] () { (?) [self: nil] -> T } -> ^(?) [self: nil] -> T
|
|
402
|
+
| [T, S] (self: S) { (?) [self: S] -> T } -> ^(?) [self: S] -> T
|
|
403
|
+
|
|
404
|
+
# <!--
|
|
405
|
+
# rdoc-file=ractor.rb
|
|
406
|
+
# - Ractor.sharable_proc{} -> sharable proc
|
|
407
|
+
# -->
|
|
408
|
+
# Same as Ractor.sharable_proc, but returns lambda proc.
|
|
409
|
+
#
|
|
410
|
+
def self.shareable_lambda: [T] () { (?) [self: nil] -> T } -> ^(?) [self: nil] -> T
|
|
411
|
+
| [T, S] (self: S) { (?) [self: S] -> T } -> ^(?) [self: S] -> T
|
|
412
|
+
|
|
591
413
|
# <!--
|
|
592
414
|
# rdoc-file=ractor.rb
|
|
593
415
|
# - Ractor.store_if_absent(key){ init_block }
|
|
594
416
|
# -->
|
|
595
|
-
# If the
|
|
417
|
+
# If the corresponding value is not set, yield a value with init_block and store
|
|
596
418
|
# the value in thread-safe manner. This method returns corresponding stored
|
|
597
419
|
# value.
|
|
598
420
|
#
|
|
@@ -607,47 +429,7 @@ class Ractor
|
|
|
607
429
|
|
|
608
430
|
# <!--
|
|
609
431
|
# rdoc-file=ractor.rb
|
|
610
|
-
# -
|
|
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)
|
|
432
|
+
# - <<(...)
|
|
651
433
|
# -->
|
|
652
434
|
#
|
|
653
435
|
alias << send
|
|
@@ -656,58 +438,50 @@ class Ractor
|
|
|
656
438
|
# rdoc-file=ractor.rb
|
|
657
439
|
# - [](sym)
|
|
658
440
|
# -->
|
|
659
|
-
# get a value from ractor-local storage
|
|
441
|
+
# get a value from ractor-local storage for current Ractor Obsolete and use
|
|
660
442
|
# Ractor.[] instead.
|
|
661
443
|
#
|
|
444
|
+
%a{deprecated: Use Ractor.[] instead}
|
|
662
445
|
def []: (interned sym) -> untyped
|
|
663
446
|
|
|
664
447
|
# <!--
|
|
665
448
|
# rdoc-file=ractor.rb
|
|
666
449
|
# - []=(sym, val)
|
|
667
450
|
# -->
|
|
668
|
-
# set a value in ractor-local storage
|
|
451
|
+
# set a value in ractor-local storage for current Ractor Obsolete and use
|
|
669
452
|
# Ractor.[]= instead.
|
|
670
453
|
#
|
|
454
|
+
%a{deprecated: Use Ractor.[]= instead}
|
|
671
455
|
def []=: [T] (interned sym, T val) -> T
|
|
672
456
|
|
|
673
457
|
# <!--
|
|
674
458
|
# rdoc-file=ractor.rb
|
|
675
|
-
# - ractor.
|
|
459
|
+
# - ractor.default_port -> port object
|
|
676
460
|
# -->
|
|
677
|
-
#
|
|
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)
|
|
461
|
+
# return default port of the Ractor.
|
|
686
462
|
#
|
|
687
|
-
def
|
|
463
|
+
def default_port: () -> Port[untyped]
|
|
688
464
|
|
|
689
465
|
# <!--
|
|
690
466
|
# rdoc-file=ractor.rb
|
|
691
|
-
# -
|
|
467
|
+
# - inspect()
|
|
692
468
|
# -->
|
|
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.
|
|
696
469
|
#
|
|
697
|
-
|
|
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
|
|
470
|
+
def inspect: () -> String
|
|
704
471
|
|
|
705
472
|
# <!--
|
|
706
473
|
# rdoc-file=ractor.rb
|
|
707
|
-
# -
|
|
474
|
+
# - ractor.join -> self
|
|
708
475
|
# -->
|
|
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.
|
|
709
478
|
#
|
|
710
|
-
|
|
479
|
+
# Ractor.new{}.join #=> ractor
|
|
480
|
+
#
|
|
481
|
+
# Ractor.new{ raise "foo" }.join
|
|
482
|
+
# #=> raise an exception "foo (RuntimeError)"
|
|
483
|
+
#
|
|
484
|
+
def join: () -> self
|
|
711
485
|
|
|
712
486
|
# <!--
|
|
713
487
|
# rdoc-file=ractor.rb
|
|
@@ -719,162 +493,60 @@ class Ractor
|
|
|
719
493
|
|
|
720
494
|
# <!--
|
|
721
495
|
# rdoc-file=ractor.rb
|
|
722
|
-
# - ractor.
|
|
496
|
+
# - ractor.monitor(port) -> self
|
|
723
497
|
# -->
|
|
724
|
-
#
|
|
725
|
-
#
|
|
726
|
-
#
|
|
727
|
-
#
|
|
728
|
-
# puts "Received #{value}"
|
|
729
|
-
# end
|
|
730
|
-
# r.send 'message'
|
|
731
|
-
# # Prints: "Received: message"
|
|
732
|
-
#
|
|
733
|
-
# The method is non-blocking (will return immediately even if the ractor is not
|
|
734
|
-
# ready to receive anything):
|
|
498
|
+
# Register port as a monitoring port. If the ractor terminated, the port
|
|
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.
|
|
735
502
|
#
|
|
736
|
-
# r = Ractor.new
|
|
737
|
-
# r.
|
|
738
|
-
#
|
|
739
|
-
# # Prints: "Sent successfully" immediately
|
|
503
|
+
# r = Ractor.new{ some_task() }
|
|
504
|
+
# r.monitor(port = Ractor::Port.new)
|
|
505
|
+
# port.receive #=> :exited and r is terminated
|
|
740
506
|
#
|
|
741
|
-
#
|
|
742
|
-
# Ractor::
|
|
507
|
+
# r = Ractor.new{ raise "foo" }
|
|
508
|
+
# r.monitor(port = Ractor::Port.new)
|
|
509
|
+
# port.receive #=> :terminated and r is terminated with an exception "foo"
|
|
743
510
|
#
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
#
|
|
747
|
-
#
|
|
748
|
-
#
|
|
749
|
-
#
|
|
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
|
|
511
|
+
def monitor: [T < Symbol] (Port[T]) -> untyped
|
|
512
|
+
|
|
513
|
+
# <!--
|
|
514
|
+
# rdoc-file=ractor.rb
|
|
515
|
+
# - ractor.send(msg) -> self
|
|
516
|
+
# -->
|
|
517
|
+
# It is equivalent to default_port.send(msg)
|
|
802
518
|
#
|
|
803
519
|
def send: (untyped obj, ?move: boolish) -> Ractor
|
|
804
520
|
|
|
805
521
|
# <!--
|
|
806
522
|
# rdoc-file=ractor.rb
|
|
807
|
-
# -
|
|
523
|
+
# - to_s()
|
|
808
524
|
# -->
|
|
809
|
-
# Get a message from the ractor's outgoing port, which was put there by
|
|
810
|
-
# Ractor.yield or at ractor's termination.
|
|
811
|
-
#
|
|
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.
|
|
827
525
|
#
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
#
|
|
831
|
-
#
|
|
832
|
-
#
|
|
833
|
-
#
|
|
834
|
-
#
|
|
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
|
|
526
|
+
alias to_s inspect
|
|
527
|
+
|
|
528
|
+
# <!--
|
|
529
|
+
# rdoc-file=ractor.rb
|
|
530
|
+
# - ractor.unmonitor(port) -> self
|
|
531
|
+
# -->
|
|
532
|
+
# Unregister port from the monitoring ports.
|
|
869
533
|
#
|
|
870
|
-
def
|
|
534
|
+
def unmonitor: (Port[untyped]) -> self
|
|
871
535
|
|
|
872
536
|
# <!--
|
|
873
537
|
# rdoc-file=ractor.rb
|
|
874
|
-
# -
|
|
538
|
+
# - ractor.value -> obj
|
|
875
539
|
# -->
|
|
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.
|
|
876
543
|
#
|
|
877
|
-
|
|
544
|
+
# r = Ractor.new{ [1, 2] }
|
|
545
|
+
# r.value #=> [1, 2] (unshareable object)
|
|
546
|
+
#
|
|
547
|
+
# Ractor.new(r){|r| r.value} #=> Ractor::Error
|
|
548
|
+
#
|
|
549
|
+
def value: () -> untyped
|
|
878
550
|
|
|
879
551
|
private
|
|
880
552
|
|
|
@@ -938,9 +610,15 @@ class Ractor
|
|
|
938
610
|
class ClosedError < StopIteration
|
|
939
611
|
end
|
|
940
612
|
|
|
613
|
+
# <!-- rdoc-file=ractor.c -->
|
|
614
|
+
# The parent class of Ractor-related error classes.
|
|
615
|
+
#
|
|
941
616
|
class Error < RuntimeError
|
|
942
617
|
end
|
|
943
618
|
|
|
619
|
+
# <!-- rdoc-file=ractor.c -->
|
|
620
|
+
# Raised on attempt to make a Ractor-unshareable object Ractor-shareable.
|
|
621
|
+
#
|
|
944
622
|
class IsolationError < Ractor::Error
|
|
945
623
|
end
|
|
946
624
|
|
|
@@ -1037,6 +715,166 @@ class Ractor
|
|
|
1037
715
|
def method_missing: (*untyped) -> untyped
|
|
1038
716
|
end
|
|
1039
717
|
|
|
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
|
+
|
|
1040
878
|
# <!-- rdoc-file=ractor.c -->
|
|
1041
879
|
# Raised on attempt to Ractor#take if there was an uncaught exception in the
|
|
1042
880
|
# Ractor. Its `cause` will contain the original exception, and `ractor` is the
|
|
@@ -1059,6 +897,9 @@ class Ractor
|
|
|
1059
897
|
def ractor: () -> Ractor
|
|
1060
898
|
end
|
|
1061
899
|
|
|
900
|
+
# <!-- rdoc-file=ractor.c -->
|
|
901
|
+
# Raised when Ractor-unsafe C-methods is invoked by a non-main Ractor.
|
|
902
|
+
#
|
|
1062
903
|
class UnsafeError < Ractor::Error
|
|
1063
904
|
end
|
|
1064
905
|
|