rbs 4.0.0.dev.4 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +14 -14
- data/.github/workflows/bundle-update.yml +60 -0
- data/.github/workflows/c-check.yml +18 -11
- data/.github/workflows/comments.yml +5 -3
- data/.github/workflows/dependabot.yml +2 -2
- data/.github/workflows/ruby.yml +27 -34
- data/.github/workflows/rust.yml +95 -0
- data/.github/workflows/typecheck.yml +2 -2
- data/.github/workflows/windows.yml +2 -2
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +323 -0
- data/README.md +1 -1
- data/Rakefile +43 -33
- data/Steepfile +1 -0
- data/config.yml +426 -24
- data/core/array.rbs +307 -227
- data/core/basic_object.rbs +9 -8
- data/core/binding.rbs +0 -2
- data/core/builtin.rbs +2 -2
- data/core/class.rbs +6 -5
- data/core/comparable.rbs +55 -34
- data/core/complex.rbs +104 -78
- data/core/dir.rbs +61 -49
- data/core/encoding.rbs +12 -15
- data/core/enumerable.rbs +179 -87
- data/core/enumerator/arithmetic_sequence.rbs +70 -0
- data/core/enumerator.rbs +65 -2
- data/core/errno.rbs +11 -2
- data/core/errors.rbs +58 -29
- data/core/exception.rbs +13 -13
- data/core/fiber.rbs +74 -54
- data/core/file.rbs +280 -177
- data/core/file_test.rbs +3 -3
- data/core/float.rbs +257 -92
- data/core/gc.rbs +425 -281
- data/core/hash.rbs +1045 -739
- data/core/integer.rbs +135 -137
- data/core/io/buffer.rbs +53 -42
- data/core/io/wait.rbs +13 -35
- data/core/io.rbs +192 -144
- data/core/kernel.rbs +216 -155
- data/core/marshal.rbs +4 -4
- data/core/match_data.rbs +15 -13
- data/core/math.rbs +107 -66
- data/core/method.rbs +69 -33
- data/core/module.rbs +244 -106
- data/core/nil_class.rbs +7 -6
- data/core/numeric.rbs +74 -63
- data/core/object.rbs +9 -11
- data/core/object_space.rbs +30 -23
- data/core/pathname.rbs +1322 -0
- data/core/proc.rbs +95 -58
- data/core/process.rbs +222 -202
- data/core/ractor.rbs +371 -515
- data/core/random.rbs +21 -3
- data/core/range.rbs +159 -57
- data/core/rational.rbs +60 -89
- data/core/rbs/unnamed/argf.rbs +60 -53
- data/core/rbs/unnamed/env_class.rbs +19 -14
- data/core/rbs/unnamed/main_class.rbs +123 -0
- data/core/rbs/unnamed/random.rbs +11 -118
- data/core/regexp.rbs +258 -214
- data/core/ruby.rbs +53 -0
- data/core/ruby_vm.rbs +38 -34
- data/core/rubygems/config_file.rbs +5 -5
- data/core/rubygems/errors.rbs +4 -71
- data/core/rubygems/requirement.rbs +5 -5
- data/core/rubygems/rubygems.rbs +16 -82
- data/core/rubygems/version.rbs +2 -3
- data/core/set.rbs +490 -360
- data/core/signal.rbs +26 -16
- data/core/string.rbs +3234 -1285
- data/core/struct.rbs +27 -26
- data/core/symbol.rbs +41 -34
- data/core/thread.rbs +135 -67
- data/core/time.rbs +81 -50
- data/core/trace_point.rbs +41 -35
- data/core/true_class.rbs +2 -2
- data/core/unbound_method.rbs +24 -16
- data/core/warning.rbs +7 -7
- data/docs/aliases.md +79 -0
- data/docs/collection.md +3 -3
- data/docs/config.md +171 -0
- data/docs/encoding.md +56 -0
- data/docs/gem.md +0 -1
- data/docs/inline.md +576 -0
- data/docs/sigs.md +3 -3
- data/docs/syntax.md +46 -16
- data/docs/type_fingerprint.md +21 -0
- data/exe/rbs +1 -1
- data/ext/rbs_extension/ast_translation.c +544 -116
- data/ext/rbs_extension/ast_translation.h +3 -0
- data/ext/rbs_extension/class_constants.c +16 -2
- data/ext/rbs_extension/class_constants.h +8 -0
- data/ext/rbs_extension/extconf.rb +5 -1
- data/ext/rbs_extension/legacy_location.c +33 -56
- data/ext/rbs_extension/legacy_location.h +37 -0
- data/ext/rbs_extension/main.c +44 -35
- data/include/rbs/ast.h +448 -173
- data/include/rbs/defines.h +27 -0
- data/include/rbs/lexer.h +30 -11
- data/include/rbs/location.h +25 -44
- data/include/rbs/parser.h +6 -6
- data/include/rbs/string.h +0 -2
- data/include/rbs/util/rbs_allocator.h +34 -13
- data/include/rbs/util/rbs_assert.h +12 -1
- data/include/rbs/util/rbs_constant_pool.h +0 -3
- data/include/rbs/util/rbs_encoding.h +2 -0
- data/include/rbs/util/rbs_unescape.h +2 -1
- data/include/rbs.h +8 -0
- data/lib/rbs/ast/annotation.rb +1 -1
- data/lib/rbs/ast/comment.rb +1 -1
- data/lib/rbs/ast/declarations.rb +10 -10
- data/lib/rbs/ast/members.rb +14 -14
- data/lib/rbs/ast/ruby/annotations.rb +293 -3
- data/lib/rbs/ast/ruby/comment_block.rb +24 -0
- data/lib/rbs/ast/ruby/declarations.rb +198 -3
- data/lib/rbs/ast/ruby/helpers/constant_helper.rb +4 -0
- data/lib/rbs/ast/ruby/members.rb +532 -22
- data/lib/rbs/ast/type_param.rb +24 -4
- data/lib/rbs/buffer.rb +20 -15
- data/lib/rbs/cli/diff.rb +16 -15
- data/lib/rbs/cli/validate.rb +38 -106
- data/lib/rbs/cli.rb +52 -19
- data/lib/rbs/collection/config/lockfile_generator.rb +14 -2
- data/lib/rbs/collection/sources/git.rb +1 -0
- data/lib/rbs/definition.rb +1 -1
- data/lib/rbs/definition_builder/ancestor_builder.rb +62 -9
- data/lib/rbs/definition_builder/method_builder.rb +20 -0
- data/lib/rbs/definition_builder.rb +147 -25
- data/lib/rbs/diff.rb +7 -1
- data/lib/rbs/environment.rb +227 -74
- data/lib/rbs/environment_loader.rb +0 -6
- data/lib/rbs/errors.rb +27 -18
- data/lib/rbs/inline_parser.rb +342 -6
- data/lib/rbs/location_aux.rb +1 -1
- data/lib/rbs/locator.rb +5 -1
- data/lib/rbs/method_type.rb +5 -3
- data/lib/rbs/parser_aux.rb +20 -7
- data/lib/rbs/prototype/helpers.rb +57 -0
- data/lib/rbs/prototype/rb.rb +3 -28
- data/lib/rbs/prototype/rbi.rb +3 -20
- data/lib/rbs/prototype/runtime.rb +8 -0
- data/lib/rbs/resolver/constant_resolver.rb +2 -2
- data/lib/rbs/resolver/type_name_resolver.rb +116 -38
- data/lib/rbs/subtractor.rb +3 -1
- data/lib/rbs/test/type_check.rb +19 -2
- data/lib/rbs/type_name.rb +1 -1
- data/lib/rbs/types.rb +88 -78
- data/lib/rbs/unit_test/type_assertions.rb +35 -8
- data/lib/rbs/validator.rb +2 -2
- data/lib/rbs/version.rb +1 -1
- data/lib/rbs.rb +1 -2
- data/lib/rdoc/discover.rb +1 -1
- data/lib/rdoc_plugin/parser.rb +1 -1
- data/rbs.gemspec +4 -3
- data/rust/.gitignore +1 -0
- data/rust/Cargo.lock +378 -0
- data/rust/Cargo.toml +7 -0
- data/rust/ruby-rbs/Cargo.toml +22 -0
- data/rust/ruby-rbs/build.rs +764 -0
- data/rust/ruby-rbs/examples/locations.rs +60 -0
- data/rust/ruby-rbs/src/lib.rs +1 -0
- data/rust/ruby-rbs/src/node/mod.rs +742 -0
- data/rust/ruby-rbs/tests/sanity.rs +47 -0
- data/rust/ruby-rbs/vendor/rbs/config.yml +1 -0
- data/rust/ruby-rbs-sys/Cargo.toml +23 -0
- data/rust/ruby-rbs-sys/build.rs +204 -0
- data/rust/ruby-rbs-sys/src/lib.rs +50 -0
- data/rust/ruby-rbs-sys/vendor/rbs/include +1 -0
- data/rust/ruby-rbs-sys/vendor/rbs/src +1 -0
- data/rust/ruby-rbs-sys/wrapper.h +1 -0
- data/schema/typeParam.json +17 -1
- data/sig/ast/ruby/annotations.rbs +315 -4
- data/sig/ast/ruby/comment_block.rbs +8 -0
- data/sig/ast/ruby/declarations.rbs +102 -4
- data/sig/ast/ruby/members.rbs +108 -2
- data/sig/cli/diff.rbs +5 -11
- data/sig/cli/validate.rbs +12 -8
- data/sig/cli.rbs +18 -18
- data/sig/definition.rbs +6 -1
- data/sig/definition_builder.rbs +2 -0
- data/sig/environment.rbs +70 -12
- data/sig/errors.rbs +13 -14
- data/sig/inline_parser.rbs +39 -2
- data/sig/locator.rbs +0 -2
- data/sig/manifest.yaml +0 -1
- data/sig/method_builder.rbs +3 -1
- data/sig/parser.rbs +31 -13
- data/sig/prototype/helpers.rbs +2 -0
- data/sig/resolver/type_name_resolver.rbs +35 -7
- data/sig/source.rbs +3 -3
- data/sig/type_param.rbs +13 -8
- data/sig/types.rbs +6 -7
- data/sig/unit_test/spy.rbs +0 -8
- data/sig/unit_test/type_assertions.rbs +11 -0
- data/src/ast.c +410 -153
- data/src/lexer.c +1392 -1313
- data/src/lexer.re +3 -0
- data/src/lexstate.c +58 -37
- data/src/location.c +8 -48
- data/src/parser.c +977 -516
- data/src/string.c +0 -48
- data/src/util/rbs_allocator.c +89 -71
- data/src/util/rbs_assert.c +1 -1
- data/src/util/rbs_buffer.c +2 -2
- data/src/util/rbs_constant_pool.c +10 -14
- data/src/util/rbs_encoding.c +4 -8
- data/src/util/rbs_unescape.c +56 -20
- data/stdlib/bigdecimal/0/big_decimal.rbs +116 -98
- data/stdlib/bigdecimal-math/0/big_math.rbs +169 -8
- data/stdlib/cgi/0/core.rbs +9 -393
- data/stdlib/cgi/0/manifest.yaml +1 -0
- data/stdlib/cgi-escape/0/escape.rbs +171 -0
- data/stdlib/coverage/0/coverage.rbs +7 -4
- data/stdlib/date/0/date.rbs +92 -79
- data/stdlib/date/0/date_time.rbs +25 -24
- data/stdlib/delegate/0/delegator.rbs +10 -7
- data/stdlib/did_you_mean/0/did_you_mean.rbs +17 -16
- data/stdlib/digest/0/digest.rbs +110 -0
- data/stdlib/erb/0/erb.rbs +748 -347
- data/stdlib/etc/0/etc.rbs +55 -50
- data/stdlib/fileutils/0/fileutils.rbs +158 -139
- data/stdlib/forwardable/0/forwardable.rbs +13 -10
- data/stdlib/io-console/0/io-console.rbs +2 -2
- data/stdlib/json/0/json.rbs +217 -136
- data/stdlib/monitor/0/monitor.rbs +3 -3
- data/stdlib/net-http/0/net-http.rbs +162 -134
- data/stdlib/objspace/0/objspace.rbs +17 -34
- data/stdlib/open-uri/0/open-uri.rbs +48 -8
- data/stdlib/open3/0/open3.rbs +469 -10
- data/stdlib/openssl/0/openssl.rbs +475 -357
- data/stdlib/optparse/0/optparse.rbs +26 -17
- data/stdlib/pathname/0/pathname.rbs +11 -1381
- data/stdlib/pp/0/pp.rbs +9 -8
- data/stdlib/prettyprint/0/prettyprint.rbs +7 -7
- data/stdlib/pstore/0/pstore.rbs +35 -30
- data/stdlib/psych/0/psych.rbs +65 -12
- data/stdlib/psych/0/store.rbs +2 -4
- data/stdlib/pty/0/pty.rbs +9 -6
- data/stdlib/random-formatter/0/random-formatter.rbs +277 -0
- data/stdlib/rdoc/0/code_object.rbs +2 -1
- data/stdlib/rdoc/0/parser.rbs +1 -1
- data/stdlib/rdoc/0/rdoc.rbs +1 -1
- data/stdlib/rdoc/0/store.rbs +1 -1
- data/stdlib/resolv/0/resolv.rbs +25 -68
- data/stdlib/ripper/0/ripper.rbs +22 -19
- data/stdlib/securerandom/0/manifest.yaml +2 -0
- data/stdlib/securerandom/0/securerandom.rbs +7 -20
- data/stdlib/shellwords/0/shellwords.rbs +2 -2
- data/stdlib/singleton/0/singleton.rbs +3 -0
- data/stdlib/socket/0/addrinfo.rbs +7 -7
- data/stdlib/socket/0/basic_socket.rbs +3 -3
- data/stdlib/socket/0/ip_socket.rbs +10 -8
- data/stdlib/socket/0/socket.rbs +23 -10
- data/stdlib/socket/0/tcp_server.rbs +1 -1
- data/stdlib/socket/0/tcp_socket.rbs +11 -3
- data/stdlib/socket/0/udp_socket.rbs +1 -1
- data/stdlib/socket/0/unix_server.rbs +1 -1
- data/stdlib/stringio/0/stringio.rbs +1177 -85
- data/stdlib/strscan/0/string_scanner.rbs +27 -25
- data/stdlib/tempfile/0/tempfile.rbs +25 -21
- data/stdlib/time/0/time.rbs +8 -6
- data/stdlib/timeout/0/timeout.rbs +63 -7
- data/stdlib/tsort/0/cyclic.rbs +3 -0
- data/stdlib/tsort/0/tsort.rbs +7 -6
- data/stdlib/uri/0/common.rbs +42 -20
- data/stdlib/uri/0/file.rbs +3 -3
- data/stdlib/uri/0/generic.rbs +26 -18
- data/stdlib/uri/0/http.rbs +2 -2
- data/stdlib/uri/0/ldap.rbs +2 -2
- data/stdlib/uri/0/mailto.rbs +3 -3
- data/stdlib/uri/0/rfc2396_parser.rbs +12 -12
- data/stdlib/zlib/0/deflate.rbs +4 -3
- data/stdlib/zlib/0/gzip_reader.rbs +6 -6
- data/stdlib/zlib/0/gzip_writer.rbs +14 -12
- data/stdlib/zlib/0/inflate.rbs +1 -1
- data/stdlib/zlib/0/need_dict.rbs +1 -1
- data/stdlib/zlib/0/zstream.rbs +1 -0
- metadata +50 -6
data/core/ractor.rbs
CHANGED
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
# <!-- rdoc-file=ractor.rb -->
|
|
2
|
-
# Ractor
|
|
3
|
-
# parallel execution.
|
|
4
|
-
#
|
|
5
|
-
# Ractor.new makes a new Ractor, which can run in parallel.
|
|
2
|
+
# Ractor.new creates a new Ractor, which can run in parallel with other ractors.
|
|
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
|
|
13
10
|
# to this: across ractors, thread-safety concerns such as data-races and
|
|
14
11
|
# race-conditions are not possible. The other benefit is parallelism.
|
|
15
12
|
#
|
|
16
|
-
# To achieve this, object sharing is limited across ractors.
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
13
|
+
# To achieve this, object sharing is limited across ractors. Unlike in threads,
|
|
14
|
+
# ractors can't access all the objects available in other ractors. For example,
|
|
15
|
+
# objects normally available through variables in the outer scope are prohibited
|
|
16
|
+
# from being used across ractors.
|
|
20
17
|
#
|
|
21
18
|
# a = 1
|
|
22
19
|
# r = Ractor.new {puts "I am in Ractor! a=#{a}"}
|
|
@@ -27,80 +24,37 @@
|
|
|
27
24
|
# a = 1
|
|
28
25
|
# r = Ractor.new(a) { |a1| puts "I am in Ractor! a=#{a1}"}
|
|
29
26
|
#
|
|
30
|
-
# On CRuby (the default implementation), Global Virtual Machine Lock (GVL)
|
|
31
|
-
# held per ractor, so ractors can
|
|
32
|
-
#
|
|
27
|
+
# On CRuby (the default implementation), the Global Virtual Machine Lock (GVL)
|
|
28
|
+
# is held per ractor, so ractors can run in parallel. This is unlike the
|
|
29
|
+
# situation with threads on CRuby.
|
|
33
30
|
#
|
|
34
31
|
# Instead of accessing shared state, objects should be passed to and from
|
|
35
32
|
# ractors by sending and receiving them as messages.
|
|
36
33
|
#
|
|
37
34
|
# a = 1
|
|
38
35
|
# r = Ractor.new do
|
|
39
|
-
# a_in_ractor = receive # receive blocks until
|
|
36
|
+
# a_in_ractor = receive # receive blocks the Thread until our default port gets sent a message
|
|
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
|
#
|
|
95
|
-
# When an object is sent to
|
|
96
|
-
#
|
|
97
|
-
#
|
|
98
|
-
#
|
|
49
|
+
# When an object is sent to a ractor, it's important to understand whether the
|
|
50
|
+
# object is shareable or unshareable. Most Ruby objects are unshareable objects.
|
|
51
|
+
# Even frozen objects can be unshareable if they contain (through their instance
|
|
52
|
+
# variables) unfrozen objects.
|
|
99
53
|
#
|
|
100
|
-
# Shareable objects are those which can be used by several
|
|
101
|
-
# compromising thread-safety, for example numbers, `true` and `false`.
|
|
54
|
+
# Shareable objects are those which can be used by several ractors at once
|
|
55
|
+
# without compromising thread-safety, for example numbers, `true` and `false`.
|
|
102
56
|
# Ractor.shareable? allows you to check this, and Ractor.make_shareable tries to
|
|
103
|
-
# make the object shareable if it's not already
|
|
57
|
+
# make the object shareable if it's not already and gives an error if it can't
|
|
104
58
|
# do it.
|
|
105
59
|
#
|
|
106
60
|
# Ractor.shareable?(1) #=> true -- numbers and other immutable basic values are shareable
|
|
@@ -116,25 +70,25 @@
|
|
|
116
70
|
# ary[0].frozen? #=> true
|
|
117
71
|
# ary[1].frozen? #=> true
|
|
118
72
|
#
|
|
119
|
-
# When a shareable object is sent
|
|
120
|
-
#
|
|
121
|
-
#
|
|
122
|
-
# the
|
|
123
|
-
#
|
|
73
|
+
# When a shareable object is sent via #send, no additional processing occurs on
|
|
74
|
+
# it and it becomes usable by both ractors. When an unshareable object is sent,
|
|
75
|
+
# it can be either *copied* or *moved*. Copying is the default, and it copies
|
|
76
|
+
# the object fully by deep cloning (Object#clone) the non-shareable parts of its
|
|
77
|
+
# structure.
|
|
124
78
|
#
|
|
125
|
-
# data = ['foo', 'bar'.freeze]
|
|
79
|
+
# data = ['foo'.dup, 'bar'.freeze]
|
|
126
80
|
# r = Ractor.new do
|
|
127
81
|
# data2 = Ractor.receive
|
|
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:
|
|
135
89
|
#
|
|
136
|
-
# In ractor:
|
|
137
|
-
# Outside :
|
|
90
|
+
# In ractor: 8, 16, 24
|
|
91
|
+
# Outside : 32, 40, 24
|
|
138
92
|
#
|
|
139
93
|
# Note that the object ids of the array and the non-frozen string inside the
|
|
140
94
|
# array have changed in the ractor because they are different objects. The
|
|
@@ -142,8 +96,9 @@
|
|
|
142
96
|
# object.
|
|
143
97
|
#
|
|
144
98
|
# Deep cloning of objects may be slow, and sometimes impossible. Alternatively,
|
|
145
|
-
#
|
|
146
|
-
# object to the receiving ractor, making it inaccessible to the
|
|
99
|
+
# <code>move: true</code> may be used during sending. This will *move* the
|
|
100
|
+
# unshareable object to the receiving ractor, making it inaccessible to the
|
|
101
|
+
# sending ractor.
|
|
147
102
|
#
|
|
148
103
|
# data = ['foo', 'bar']
|
|
149
104
|
# r = Ractor.new do
|
|
@@ -151,7 +106,7 @@
|
|
|
151
106
|
# puts "In ractor: #{data_in_ractor.object_id}, #{data_in_ractor[0].object_id}"
|
|
152
107
|
# end
|
|
153
108
|
# r.send(data, move: true)
|
|
154
|
-
# r.
|
|
109
|
+
# r.join
|
|
155
110
|
# puts "Outside: moved? #{Ractor::MovedObject === data}"
|
|
156
111
|
# puts "Outside: #{data.inspect}"
|
|
157
112
|
#
|
|
@@ -161,14 +116,14 @@
|
|
|
161
116
|
# Outside: moved? true
|
|
162
117
|
# test.rb:9:in `method_missing': can not send any methods to a moved object (Ractor::MovedError)
|
|
163
118
|
#
|
|
164
|
-
# Notice that even `inspect`
|
|
119
|
+
# Notice that even `inspect` and more basic methods like `__id__` are
|
|
165
120
|
# inaccessible on a moved object.
|
|
166
121
|
#
|
|
167
|
-
# Class and Module objects are shareable
|
|
168
|
-
# shared between ractors. Ractor objects are also shareable. All operations
|
|
169
|
-
# shareable objects are thread-safe
|
|
170
|
-
#
|
|
171
|
-
#
|
|
122
|
+
# `Class` and `Module` objects are shareable and their class/module definitions
|
|
123
|
+
# are shared between ractors. Ractor objects are also shareable. All operations
|
|
124
|
+
# on shareable objects are thread-safe across ractors. Defining mutable,
|
|
125
|
+
# shareable objects in Ruby is not possible, but C extensions can introduce
|
|
126
|
+
# them.
|
|
172
127
|
#
|
|
173
128
|
# It is prohibited to access (get) instance variables of shareable objects in
|
|
174
129
|
# other ractors if the values of the variables aren't shareable. This can occur
|
|
@@ -189,7 +144,7 @@
|
|
|
189
144
|
# puts "I can't see #{cls.tricky}"
|
|
190
145
|
# cls.tricky = true # doesn't get here, but this would also raise an error
|
|
191
146
|
# end
|
|
192
|
-
# r.
|
|
147
|
+
# r.join
|
|
193
148
|
# # I see C
|
|
194
149
|
# # can not access instance variables of classes/modules from non-main Ractors (RuntimeError)
|
|
195
150
|
#
|
|
@@ -203,7 +158,7 @@
|
|
|
203
158
|
# puts "GOOD=#{GOOD}"
|
|
204
159
|
# puts "BAD=#{BAD}"
|
|
205
160
|
# end
|
|
206
|
-
# r.
|
|
161
|
+
# r.join
|
|
207
162
|
# # GOOD=good
|
|
208
163
|
# # can not access non-shareable objects in constant Object::BAD by non-main Ractor. (NameError)
|
|
209
164
|
#
|
|
@@ -213,12 +168,12 @@
|
|
|
213
168
|
# puts "I see #{C}"
|
|
214
169
|
# puts "I can't see #{C.tricky}"
|
|
215
170
|
# end
|
|
216
|
-
# r.
|
|
171
|
+
# r.join
|
|
217
172
|
# # I see C
|
|
218
173
|
# # can not access instance variables of classes/modules from non-main Ractors (RuntimeError)
|
|
219
174
|
#
|
|
220
|
-
# See also the description of
|
|
221
|
-
# syntax](rdoc-ref:syntax/comments.rdoc) explanation.
|
|
175
|
+
# See also the description of <code># shareable_constant_value</code> pragma in
|
|
176
|
+
# [Comments syntax](rdoc-ref:syntax/comments.rdoc) explanation.
|
|
222
177
|
#
|
|
223
178
|
# ## Ractors vs threads
|
|
224
179
|
#
|
|
@@ -229,20 +184,21 @@
|
|
|
229
184
|
# a = 1
|
|
230
185
|
# Thread.new {puts "Thread in ractor: a=#{a}"}.join
|
|
231
186
|
# end
|
|
232
|
-
# r.
|
|
187
|
+
# r.join
|
|
233
188
|
# # Here "Thread in ractor: a=1" will be printed
|
|
234
189
|
#
|
|
235
190
|
# ## Note on code examples
|
|
236
191
|
#
|
|
237
192
|
# In the examples below, sometimes we use the following method to wait for
|
|
238
|
-
# ractors
|
|
193
|
+
# ractors to make progress or finish.
|
|
239
194
|
#
|
|
240
195
|
# def wait
|
|
241
196
|
# sleep(0.1)
|
|
242
197
|
# end
|
|
243
198
|
#
|
|
244
|
-
#
|
|
245
|
-
# code. Most of the time, #
|
|
199
|
+
# This is **only for demonstration purposes** and shouldn't be used in a real
|
|
200
|
+
# code. Most of the time, #join is used to wait for ractors to finish and
|
|
201
|
+
# Ractor.receive is used to wait for messages.
|
|
246
202
|
#
|
|
247
203
|
# ## Reference
|
|
248
204
|
#
|
|
@@ -261,7 +217,7 @@ class Ractor
|
|
|
261
217
|
# rdoc-file=ractor.rb
|
|
262
218
|
# - [](sym)
|
|
263
219
|
# -->
|
|
264
|
-
#
|
|
220
|
+
# Gets a value from ractor-local storage for the current Ractor.
|
|
265
221
|
#
|
|
266
222
|
def self.[]: (Symbol) -> untyped
|
|
267
223
|
|
|
@@ -269,7 +225,7 @@ class Ractor
|
|
|
269
225
|
# rdoc-file=ractor.rb
|
|
270
226
|
# - []=(sym, val)
|
|
271
227
|
# -->
|
|
272
|
-
#
|
|
228
|
+
# Sets a value in ractor-local storage for the current Ractor.
|
|
273
229
|
#
|
|
274
230
|
def self.[]=: (Symbol, untyped) -> untyped
|
|
275
231
|
|
|
@@ -277,13 +233,13 @@ class Ractor
|
|
|
277
233
|
# rdoc-file=ractor.rb
|
|
278
234
|
# - count()
|
|
279
235
|
# -->
|
|
280
|
-
# Returns the number of
|
|
236
|
+
# Returns the number of ractors currently running or blocking (waiting).
|
|
281
237
|
#
|
|
282
238
|
# Ractor.count #=> 1
|
|
283
|
-
# r = Ractor.new(name: 'example') { Ractor.
|
|
239
|
+
# r = Ractor.new(name: 'example') { Ractor.receive }
|
|
284
240
|
# Ractor.count #=> 2 (main + example ractor)
|
|
285
|
-
# r
|
|
286
|
-
# r.
|
|
241
|
+
# r << 42 # r's Ractor.receive will resume
|
|
242
|
+
# r.join # wait for r's termination
|
|
287
243
|
# Ractor.count #=> 1
|
|
288
244
|
#
|
|
289
245
|
def self.count: () -> Integer
|
|
@@ -302,7 +258,7 @@ class Ractor
|
|
|
302
258
|
# rdoc-file=ractor.rb
|
|
303
259
|
# - main()
|
|
304
260
|
# -->
|
|
305
|
-
#
|
|
261
|
+
# Returns the main ractor.
|
|
306
262
|
#
|
|
307
263
|
def self.main: () -> Ractor
|
|
308
264
|
|
|
@@ -310,7 +266,7 @@ class Ractor
|
|
|
310
266
|
# rdoc-file=ractor.rb
|
|
311
267
|
# - main?()
|
|
312
268
|
# -->
|
|
313
|
-
#
|
|
269
|
+
# Returns true if the current ractor is the main ractor.
|
|
314
270
|
#
|
|
315
271
|
def self.main?: () -> boolish
|
|
316
272
|
|
|
@@ -318,7 +274,7 @@ class Ractor
|
|
|
318
274
|
# rdoc-file=ractor.rb
|
|
319
275
|
# - Ractor.make_shareable(obj, copy: false) -> shareable_obj
|
|
320
276
|
# -->
|
|
321
|
-
#
|
|
277
|
+
# Makes `obj` shareable between ractors.
|
|
322
278
|
#
|
|
323
279
|
# `obj` and all the objects it refers to will be frozen, unless they are already
|
|
324
280
|
# shareable.
|
|
@@ -357,13 +313,13 @@ class Ractor
|
|
|
357
313
|
# rdoc-file=ractor.rb
|
|
358
314
|
# - Ractor.new(*args, name: nil) {|*args| block } -> ractor
|
|
359
315
|
# -->
|
|
360
|
-
#
|
|
316
|
+
# Creates a new Ractor with args and a block.
|
|
361
317
|
#
|
|
362
|
-
# The given block (Proc)
|
|
363
|
-
#
|
|
318
|
+
# The given block (Proc) is isolated (can't access any outer variables). `self`
|
|
319
|
+
# inside the block will refer to the current Ractor.
|
|
364
320
|
#
|
|
365
321
|
# r = Ractor.new { puts "Hi, I am #{self.inspect}" }
|
|
366
|
-
# r.
|
|
322
|
+
# r.join
|
|
367
323
|
# # Prints "Hi, I am #<Ractor:#2 test.rb:1 running>"
|
|
368
324
|
#
|
|
369
325
|
# Any `args` passed are propagated to the block arguments by the same rules as
|
|
@@ -375,14 +331,14 @@ class Ractor
|
|
|
375
331
|
# r = Ractor.new(arg) {|received_arg|
|
|
376
332
|
# puts "Received: #{received_arg} (##{received_arg.object_id})"
|
|
377
333
|
# }
|
|
378
|
-
# r.
|
|
334
|
+
# r.join
|
|
379
335
|
# # Prints:
|
|
380
336
|
# # Passing: [1, 2, 3] (#280)
|
|
381
337
|
# # Received: [1, 2, 3] (#300)
|
|
382
338
|
#
|
|
383
339
|
# Ractor's `name` can be set for debugging purposes:
|
|
384
340
|
#
|
|
385
|
-
# r = Ractor.new(name: 'my ractor') {}; r.
|
|
341
|
+
# r = Ractor.new(name: 'my ractor') {}; r.join
|
|
386
342
|
# p r
|
|
387
343
|
# #=> #<Ractor:#3 my ractor test.rb:1 terminated>
|
|
388
344
|
#
|
|
@@ -390,128 +346,12 @@ class Ractor
|
|
|
390
346
|
|
|
391
347
|
# <!--
|
|
392
348
|
# rdoc-file=ractor.rb
|
|
393
|
-
# - Ractor.receive ->
|
|
349
|
+
# - Ractor.receive -> obj
|
|
394
350
|
# -->
|
|
395
|
-
#
|
|
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)
|
|
351
|
+
# Receives a message from the current ractor's default port.
|
|
450
352
|
#
|
|
451
353
|
def self.receive: () -> untyped
|
|
452
354
|
|
|
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
355
|
# <!--
|
|
516
356
|
# rdoc-file=ractor.rb
|
|
517
357
|
# - recv()
|
|
@@ -521,57 +361,51 @@ class Ractor
|
|
|
521
361
|
|
|
522
362
|
# <!--
|
|
523
363
|
# rdoc-file=ractor.rb
|
|
524
|
-
# - Ractor.select(*
|
|
364
|
+
# - Ractor.select(*ractors_or_ports) -> [ractor or port, obj]
|
|
525
365
|
# -->
|
|
526
|
-
#
|
|
527
|
-
#
|
|
528
|
-
#
|
|
529
|
-
#
|
|
530
|
-
#
|
|
531
|
-
#
|
|
532
|
-
#
|
|
533
|
-
#
|
|
534
|
-
#
|
|
535
|
-
#
|
|
536
|
-
#
|
|
537
|
-
#
|
|
538
|
-
#
|
|
539
|
-
#
|
|
540
|
-
#
|
|
541
|
-
#
|
|
542
|
-
# main.send 'to main'
|
|
543
|
-
# Ractor.yield 'from 1'
|
|
544
|
-
# end
|
|
545
|
-
# r2 = Ractor.new do
|
|
546
|
-
# Ractor.yield 'from 2'
|
|
366
|
+
# Blocks the current Thread until one of the given ports has received a message.
|
|
367
|
+
# Returns an array of two elements where the first element is the Port and the
|
|
368
|
+
# second is the received object. This method can also accept Ractor objects
|
|
369
|
+
# themselves, and in that case will wait until one has terminated and return a
|
|
370
|
+
# two-element array where the first element is the ractor and the second is its
|
|
371
|
+
# termination value.
|
|
372
|
+
#
|
|
373
|
+
# p1, p2 = Ractor::Port.new, Ractor::Port.new
|
|
374
|
+
# ps = [p1, p2]
|
|
375
|
+
# rs = 2.times.map do |i|
|
|
376
|
+
# Ractor.new(ps.shift, i) do |p, i|
|
|
377
|
+
# sleep rand(0.99)
|
|
378
|
+
# p.send("r#{i}")
|
|
379
|
+
# sleep rand(0.99)
|
|
380
|
+
# "r#{i} done"
|
|
381
|
+
# end
|
|
547
382
|
# end
|
|
548
383
|
#
|
|
549
|
-
#
|
|
550
|
-
#
|
|
551
|
-
#
|
|
552
|
-
#
|
|
553
|
-
#
|
|
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}"
|
|
384
|
+
# waiting_on = [p1, p2, *rs]
|
|
385
|
+
# until waiting_on.empty?
|
|
386
|
+
# received_on, obj = Ractor.select(*waiting_on)
|
|
387
|
+
# waiting_on.delete(received_on)
|
|
388
|
+
# puts obj
|
|
558
389
|
# end
|
|
559
390
|
#
|
|
560
|
-
#
|
|
561
|
-
#
|
|
562
|
-
#
|
|
563
|
-
#
|
|
564
|
-
#
|
|
565
|
-
#
|
|
566
|
-
#
|
|
567
|
-
#
|
|
568
|
-
#
|
|
569
|
-
#
|
|
570
|
-
#
|
|
571
|
-
#
|
|
572
|
-
#
|
|
391
|
+
# # r0
|
|
392
|
+
# # r1
|
|
393
|
+
# # r1 done
|
|
394
|
+
# # r0 done
|
|
395
|
+
#
|
|
396
|
+
# The following example is almost equivalent to
|
|
397
|
+
# <code>ractors.map(&:value)</code> except the thread is unblocked when any of
|
|
398
|
+
# the ractors has terminated as opposed to waiting for their termination in the
|
|
399
|
+
# array element order.
|
|
400
|
+
#
|
|
401
|
+
# values = []
|
|
402
|
+
# until ractors.empty?
|
|
403
|
+
# r, val = Ractor.select(*ractors)
|
|
404
|
+
# ractors.delete(r)
|
|
405
|
+
# values << val
|
|
406
|
+
# end
|
|
573
407
|
#
|
|
574
|
-
def self.select: (
|
|
408
|
+
def self.select: (?) -> Array[untyped]
|
|
575
409
|
|
|
576
410
|
# <!--
|
|
577
411
|
# rdoc-file=ractor.rb
|
|
@@ -579,7 +413,7 @@ class Ractor
|
|
|
579
413
|
# -->
|
|
580
414
|
# Checks if the object is shareable by ractors.
|
|
581
415
|
#
|
|
582
|
-
# Ractor.shareable?(1) #=> true -- numbers
|
|
416
|
+
# Ractor.shareable?(1) #=> true -- numbers are shareable
|
|
583
417
|
# Ractor.shareable?('foo') #=> false, unless the string is frozen due to # frozen_string_literal: true
|
|
584
418
|
# Ractor.shareable?('foo'.freeze) #=> true
|
|
585
419
|
#
|
|
@@ -588,13 +422,44 @@ class Ractor
|
|
|
588
422
|
#
|
|
589
423
|
def self.shareable?: (untyped obj) -> bool
|
|
590
424
|
|
|
425
|
+
# <!--
|
|
426
|
+
# rdoc-file=ractor.rb
|
|
427
|
+
# - Ractor.shareable_proc(self: nil){} -> shareable proc
|
|
428
|
+
# -->
|
|
429
|
+
# Returns a shareable copy of the given block's Proc. The value of `self` in the
|
|
430
|
+
# Proc will be replaced with the value passed via the <code>self:</code>
|
|
431
|
+
# keyword, or `nil` if not given.
|
|
432
|
+
#
|
|
433
|
+
# In a shareable Proc, access to any outer variables if prohibited.
|
|
434
|
+
#
|
|
435
|
+
# a = 42
|
|
436
|
+
# Ractor.shareable_proc{ p a }
|
|
437
|
+
# #=> can not isolate a Proc because it accesses outer variables (a). (ArgumentError)
|
|
438
|
+
#
|
|
439
|
+
# The value of `self` in the Proc must be a shareable object.
|
|
440
|
+
#
|
|
441
|
+
# Ractor.shareable_proc(self: self){}
|
|
442
|
+
# #=> self should be shareable: main (Ractor::IsolationError)
|
|
443
|
+
#
|
|
444
|
+
def self.shareable_proc: [T] () { (?) [self: nil] -> T } -> ^(?) [self: nil] -> T
|
|
445
|
+
| [T, S] (self: S) { (?) [self: S] -> T } -> ^(?) [self: S] -> T
|
|
446
|
+
|
|
447
|
+
# <!--
|
|
448
|
+
# rdoc-file=ractor.rb
|
|
449
|
+
# - Ractor.shareable_lambda(self: nil){} -> shareable lambda
|
|
450
|
+
# -->
|
|
451
|
+
# Same as Ractor.shareable_proc, but returns a lambda Proc.
|
|
452
|
+
#
|
|
453
|
+
def self.shareable_lambda: [T] () { (?) [self: nil] -> T } -> ^(?) [self: nil] -> T
|
|
454
|
+
| [T, S] (self: S) { (?) [self: S] -> T } -> ^(?) [self: S] -> T
|
|
455
|
+
|
|
591
456
|
# <!--
|
|
592
457
|
# rdoc-file=ractor.rb
|
|
593
458
|
# - Ractor.store_if_absent(key){ init_block }
|
|
594
459
|
# -->
|
|
595
|
-
# If the
|
|
596
|
-
# the value in thread-safe manner. This method returns
|
|
597
|
-
# value.
|
|
460
|
+
# If the corresponding ractor-local value is not set, yields a value with
|
|
461
|
+
# init_block and stores the value in a thread-safe manner. This method returns
|
|
462
|
+
# the stored value.
|
|
598
463
|
#
|
|
599
464
|
# (1..10).map{
|
|
600
465
|
# Thread.new(it){|i|
|
|
@@ -607,47 +472,7 @@ class Ractor
|
|
|
607
472
|
|
|
608
473
|
# <!--
|
|
609
474
|
# 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)
|
|
475
|
+
# - <<(...)
|
|
651
476
|
# -->
|
|
652
477
|
#
|
|
653
478
|
alias << send
|
|
@@ -656,225 +481,119 @@ class Ractor
|
|
|
656
481
|
# rdoc-file=ractor.rb
|
|
657
482
|
# - [](sym)
|
|
658
483
|
# -->
|
|
659
|
-
#
|
|
484
|
+
# Gets a value from ractor-local storage for the current Ractor. Obsolete, use
|
|
660
485
|
# Ractor.[] instead.
|
|
661
486
|
#
|
|
487
|
+
%a{deprecated: Use Ractor.[] instead}
|
|
662
488
|
def []: (interned sym) -> untyped
|
|
663
489
|
|
|
664
490
|
# <!--
|
|
665
491
|
# rdoc-file=ractor.rb
|
|
666
492
|
# - []=(sym, val)
|
|
667
493
|
# -->
|
|
668
|
-
#
|
|
494
|
+
# Sets a value in ractor-local storage for the current Ractor. Obsolete, use
|
|
669
495
|
# Ractor.[]= instead.
|
|
670
496
|
#
|
|
497
|
+
%a{deprecated: Use Ractor.[]= instead}
|
|
671
498
|
def []=: [T] (interned sym, T val) -> T
|
|
672
499
|
|
|
673
500
|
# <!--
|
|
674
501
|
# rdoc-file=ractor.rb
|
|
675
|
-
# - ractor.
|
|
502
|
+
# - ractor.default_port -> port object
|
|
676
503
|
# -->
|
|
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)
|
|
504
|
+
# Returns the default port of the Ractor.
|
|
686
505
|
#
|
|
687
|
-
def
|
|
506
|
+
def default_port: () -> Port[untyped]
|
|
688
507
|
|
|
689
508
|
# <!--
|
|
690
509
|
# rdoc-file=ractor.rb
|
|
691
|
-
# -
|
|
510
|
+
# - inspect()
|
|
692
511
|
# -->
|
|
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
512
|
#
|
|
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
|
|
513
|
+
def inspect: () -> String
|
|
704
514
|
|
|
705
515
|
# <!--
|
|
706
516
|
# rdoc-file=ractor.rb
|
|
707
|
-
# -
|
|
517
|
+
# - ractor.join -> self
|
|
708
518
|
# -->
|
|
519
|
+
# Waits for the termination of the Ractor. If the Ractor was aborted (terminated
|
|
520
|
+
# by an unhandled exception), the exception is raised in the current ractor.
|
|
709
521
|
#
|
|
710
|
-
|
|
522
|
+
# Ractor.new{}.join #=> ractor
|
|
523
|
+
#
|
|
524
|
+
# Ractor.new{ raise "foo" }.join
|
|
525
|
+
# #=> raises the exception "foo (RuntimeError)"
|
|
526
|
+
#
|
|
527
|
+
def join: () -> self
|
|
711
528
|
|
|
712
529
|
# <!--
|
|
713
530
|
# rdoc-file=ractor.rb
|
|
714
531
|
# - name()
|
|
715
532
|
# -->
|
|
716
|
-
#
|
|
533
|
+
# Returns the name set in Ractor.new, or `nil`.
|
|
717
534
|
#
|
|
718
535
|
def name: () -> String?
|
|
719
536
|
|
|
720
537
|
# <!--
|
|
721
538
|
# rdoc-file=ractor.rb
|
|
722
|
-
# - ractor.
|
|
539
|
+
# - ractor.monitor(port) -> self
|
|
723
540
|
# -->
|
|
724
|
-
#
|
|
725
|
-
#
|
|
726
|
-
# r = Ractor.new do
|
|
727
|
-
# value = Ractor.receive
|
|
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):
|
|
735
|
-
#
|
|
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.
|
|
541
|
+
# Registers the port as a monitoring port for this ractor. When the ractor
|
|
542
|
+
# terminates, the port receives a Symbol object.
|
|
766
543
|
#
|
|
767
|
-
#
|
|
768
|
-
#
|
|
769
|
-
#
|
|
770
|
-
#
|
|
771
|
-
# p msg
|
|
544
|
+
# * <code>:exited</code> is sent if the ractor terminates without an unhandled
|
|
545
|
+
# exception.
|
|
546
|
+
# * <code>:aborted</code> is sent if the ractor terminates by an unhandled
|
|
547
|
+
# exception.
|
|
772
548
|
#
|
|
773
|
-
#
|
|
549
|
+
# r = Ractor.new{ some_task() }
|
|
550
|
+
# r.monitor(port = Ractor::Port.new)
|
|
551
|
+
# port.receive #=> :exited and r is terminated
|
|
774
552
|
#
|
|
775
|
-
#
|
|
776
|
-
#
|
|
553
|
+
# r = Ractor.new{ raise "foo" }
|
|
554
|
+
# r.monitor(port = Ractor::Port.new)
|
|
555
|
+
# port.receive #=> :aborted and r is terminated by the RuntimeError "foo"
|
|
777
556
|
#
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
#
|
|
781
|
-
#
|
|
782
|
-
#
|
|
783
|
-
#
|
|
784
|
-
#
|
|
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
|
|
557
|
+
def monitor: [T < Symbol] (Port[T]) -> untyped
|
|
558
|
+
|
|
559
|
+
# <!--
|
|
560
|
+
# rdoc-file=ractor.rb
|
|
561
|
+
# - ractor.send(msg, move: false) -> self
|
|
562
|
+
# -->
|
|
563
|
+
# This is equivalent to Port#send to the ractor's #default_port.
|
|
802
564
|
#
|
|
803
565
|
def send: (untyped obj, ?move: boolish) -> Ractor
|
|
804
566
|
|
|
805
567
|
# <!--
|
|
806
568
|
# rdoc-file=ractor.rb
|
|
807
|
-
# -
|
|
569
|
+
# - to_s()
|
|
808
570
|
# -->
|
|
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
|
-
#
|
|
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
571
|
#
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
#
|
|
853
|
-
#
|
|
854
|
-
#
|
|
855
|
-
#
|
|
856
|
-
#
|
|
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
|
|
572
|
+
alias to_s inspect
|
|
573
|
+
|
|
574
|
+
# <!--
|
|
575
|
+
# rdoc-file=ractor.rb
|
|
576
|
+
# - ractor.unmonitor(port) -> self
|
|
577
|
+
# -->
|
|
578
|
+
# Unregisters the port from the monitoring ports for this ractor.
|
|
869
579
|
#
|
|
870
|
-
def
|
|
580
|
+
def unmonitor: (Port[untyped]) -> self
|
|
871
581
|
|
|
872
582
|
# <!--
|
|
873
583
|
# rdoc-file=ractor.rb
|
|
874
|
-
# -
|
|
584
|
+
# - ractor.value -> obj
|
|
875
585
|
# -->
|
|
586
|
+
# Waits for `ractor` to complete and returns its value or raises the exception
|
|
587
|
+
# which terminated the Ractor. The termination value will be moved to the
|
|
588
|
+
# calling Ractor. Therefore, at most 1 Ractor can receive another ractor's
|
|
589
|
+
# termination value.
|
|
876
590
|
#
|
|
877
|
-
|
|
591
|
+
# r = Ractor.new{ [1, 2] }
|
|
592
|
+
# r.value #=> [1, 2] (unshareable object)
|
|
593
|
+
#
|
|
594
|
+
# Ractor.new(r){|r| r.value} #=> Ractor::Error
|
|
595
|
+
#
|
|
596
|
+
def value: () -> untyped
|
|
878
597
|
|
|
879
598
|
private
|
|
880
599
|
|
|
@@ -904,49 +623,35 @@ class Ractor
|
|
|
904
623
|
# <!-- rdoc-file=ractor.c -->
|
|
905
624
|
# Raised when an attempt is made to send a message to a closed port, or to
|
|
906
625
|
# retrieve a message from a closed and empty port. Ports may be closed
|
|
907
|
-
# explicitly with Ractor#
|
|
908
|
-
#
|
|
909
|
-
#
|
|
910
|
-
# r = Ractor.new { sleep(500) }
|
|
911
|
-
# r.close_outgoing
|
|
912
|
-
# r.take # Ractor::ClosedError
|
|
913
|
-
#
|
|
914
|
-
# ClosedError is a descendant of StopIteration, so the closing of the ractor
|
|
915
|
-
# will break the loops without propagating the error:
|
|
916
|
-
#
|
|
917
|
-
# r = Ractor.new do
|
|
918
|
-
# loop do
|
|
919
|
-
# msg = receive # raises ClosedError and loop traps it
|
|
920
|
-
# puts "Received: #{msg}"
|
|
921
|
-
# end
|
|
922
|
-
# puts "loop exited"
|
|
923
|
-
# end
|
|
626
|
+
# explicitly with Ractor::Port#close and are closed implicitly when a Ractor
|
|
627
|
+
# terminates.
|
|
924
628
|
#
|
|
925
|
-
#
|
|
926
|
-
#
|
|
927
|
-
#
|
|
928
|
-
#
|
|
629
|
+
# port = Ractor::Port.new
|
|
630
|
+
# port.close
|
|
631
|
+
# port << "test" # Ractor::ClosedError
|
|
632
|
+
# port.receive # Ractor::ClosedError
|
|
929
633
|
#
|
|
930
|
-
#
|
|
931
|
-
#
|
|
932
|
-
# Received: 0
|
|
933
|
-
# Received: 1
|
|
934
|
-
# Received: 2
|
|
935
|
-
# loop exited
|
|
936
|
-
# Continue successfully
|
|
634
|
+
# ClosedError is a descendant of StopIteration, so the closing of a port will
|
|
635
|
+
# break out of loops without propagating the error.
|
|
937
636
|
#
|
|
938
637
|
class ClosedError < StopIteration
|
|
939
638
|
end
|
|
940
639
|
|
|
640
|
+
# <!-- rdoc-file=ractor.c -->
|
|
641
|
+
# The parent class of Ractor-related error classes.
|
|
642
|
+
#
|
|
941
643
|
class Error < RuntimeError
|
|
942
644
|
end
|
|
943
645
|
|
|
646
|
+
# <!-- rdoc-file=ractor.c -->
|
|
647
|
+
# Raised on attempt to make a Ractor-unshareable object Ractor-shareable.
|
|
648
|
+
#
|
|
944
649
|
class IsolationError < Ractor::Error
|
|
945
650
|
end
|
|
946
651
|
|
|
947
652
|
# <!-- rdoc-file=ractor.c -->
|
|
948
653
|
# Raised on an attempt to access an object which was moved in Ractor#send or
|
|
949
|
-
# Ractor.
|
|
654
|
+
# Ractor::Port#send.
|
|
950
655
|
#
|
|
951
656
|
# r = Ractor.new { sleep }
|
|
952
657
|
#
|
|
@@ -960,7 +665,7 @@ class Ractor
|
|
|
960
665
|
|
|
961
666
|
# <!-- rdoc-file=ractor.c -->
|
|
962
667
|
# A special object which replaces any value that was moved to another ractor in
|
|
963
|
-
# Ractor#send or Ractor.
|
|
668
|
+
# Ractor#send or Ractor::Port#send. Any attempt to access the object results in
|
|
964
669
|
# Ractor::MovedError.
|
|
965
670
|
#
|
|
966
671
|
# r = Ractor.new { receive }
|
|
@@ -1037,15 +742,163 @@ class Ractor
|
|
|
1037
742
|
def method_missing: (*untyped) -> untyped
|
|
1038
743
|
end
|
|
1039
744
|
|
|
745
|
+
# <!-- rdoc-file=ractor.rb -->
|
|
746
|
+
# Port objects transmit messages between Ractors.
|
|
747
|
+
#
|
|
748
|
+
class Port[T = untyped]
|
|
749
|
+
# <!--
|
|
750
|
+
# rdoc-file=ractor.rb
|
|
751
|
+
# - <<(obj, move: false)
|
|
752
|
+
# -->
|
|
753
|
+
#
|
|
754
|
+
alias << send
|
|
755
|
+
|
|
756
|
+
# <!--
|
|
757
|
+
# rdoc-file=ractor.rb
|
|
758
|
+
# - port.close
|
|
759
|
+
# -->
|
|
760
|
+
# Closes the port. Sending to a closed port is prohibited. Receiving is also
|
|
761
|
+
# prohibited if there are no messages in its message queue.
|
|
762
|
+
#
|
|
763
|
+
# Only the Ractor which created the port is allowed to close it.
|
|
764
|
+
#
|
|
765
|
+
# port = Ractor::Port.new
|
|
766
|
+
# Ractor.new port do |port|
|
|
767
|
+
# port.close #=> closing port by other ractors is not allowed (Ractor::Error)
|
|
768
|
+
# end.join
|
|
769
|
+
#
|
|
770
|
+
def close: () -> void
|
|
771
|
+
|
|
772
|
+
# <!--
|
|
773
|
+
# rdoc-file=ractor.rb
|
|
774
|
+
# - port.closed? -> true/false
|
|
775
|
+
# -->
|
|
776
|
+
# Returns whether or not the port is closed.
|
|
777
|
+
#
|
|
778
|
+
def closed?: () -> bool
|
|
779
|
+
|
|
780
|
+
# <!--
|
|
781
|
+
# rdoc-file=ractor.rb
|
|
782
|
+
# - port.inspect -> string
|
|
783
|
+
# -->
|
|
784
|
+
#
|
|
785
|
+
def inspect: () -> String
|
|
786
|
+
|
|
787
|
+
# <!--
|
|
788
|
+
# rdoc-file=ractor.rb
|
|
789
|
+
# - port.receive -> msg
|
|
790
|
+
# -->
|
|
791
|
+
# Receives a message from the port (which was sent there by Port#send). Only the
|
|
792
|
+
# ractor that created the port can receive messages this way.
|
|
793
|
+
#
|
|
794
|
+
# port = Ractor::Port.new
|
|
795
|
+
# r = Ractor.new port do |port|
|
|
796
|
+
# port.send('message1')
|
|
797
|
+
# end
|
|
798
|
+
#
|
|
799
|
+
# v1 = port.receive
|
|
800
|
+
# puts "Received: #{v1}"
|
|
801
|
+
# r.join
|
|
802
|
+
# # This will print: "Received: message1"
|
|
803
|
+
#
|
|
804
|
+
# The method blocks the current Thread if the message queue is empty.
|
|
805
|
+
#
|
|
806
|
+
# port = Ractor::Port.new
|
|
807
|
+
# r = Ractor.new port do |port|
|
|
808
|
+
# wait
|
|
809
|
+
# puts "Still not received"
|
|
810
|
+
# port.send('message1')
|
|
811
|
+
# wait
|
|
812
|
+
# puts "Still received only one"
|
|
813
|
+
# port.send('message2')
|
|
814
|
+
# end
|
|
815
|
+
# puts "Before first receive"
|
|
816
|
+
# v1 = port.receive
|
|
817
|
+
# puts "Received: #{v1}"
|
|
818
|
+
# v2 = port.receive
|
|
819
|
+
# puts "Received: #{v2}"
|
|
820
|
+
# r.join
|
|
821
|
+
#
|
|
822
|
+
# Output:
|
|
823
|
+
#
|
|
824
|
+
# Before first receive
|
|
825
|
+
# Still not received
|
|
826
|
+
# Received: message1
|
|
827
|
+
# Still received only one
|
|
828
|
+
# Received: message2
|
|
829
|
+
#
|
|
830
|
+
# If the port is closed and there are no more messages in the message queue, the
|
|
831
|
+
# method raises Ractor::ClosedError.
|
|
832
|
+
#
|
|
833
|
+
# port = Ractor::Port.new
|
|
834
|
+
# port.close
|
|
835
|
+
# port.receive #=> raise Ractor::ClosedError
|
|
836
|
+
#
|
|
837
|
+
def receive: () -> T
|
|
838
|
+
|
|
839
|
+
# <!--
|
|
840
|
+
# rdoc-file=ractor.rb
|
|
841
|
+
# - port.send(msg, move: false) -> self
|
|
842
|
+
# -->
|
|
843
|
+
# Sends a message to the port to be accepted by port.receive.
|
|
844
|
+
#
|
|
845
|
+
# port = Ractor::Port.new
|
|
846
|
+
# r = Ractor.new(port) do |port|
|
|
847
|
+
# port.send 'message'
|
|
848
|
+
# end
|
|
849
|
+
# value = port.receive
|
|
850
|
+
# puts "Received #{value}"
|
|
851
|
+
# # Prints: "Received: message"
|
|
852
|
+
#
|
|
853
|
+
# The method is non-blocking (it will return immediately even if the ractor that
|
|
854
|
+
# created the port is not ready to receive anything):
|
|
855
|
+
#
|
|
856
|
+
# port = Ractor::Port.new
|
|
857
|
+
# r = Ractor.new(port) do |port|
|
|
858
|
+
# port.send 'test'
|
|
859
|
+
# puts "Sent successfully"
|
|
860
|
+
# # Prints: "Sent successfully" immediately
|
|
861
|
+
# end
|
|
862
|
+
#
|
|
863
|
+
# An attempt to send to a closed port will raise Ractor::ClosedError.
|
|
864
|
+
#
|
|
865
|
+
# r = Ractor.new {Ractor::Port.new}
|
|
866
|
+
# r.join
|
|
867
|
+
# p r
|
|
868
|
+
# # "#<Ractor:#6 (irb):23 terminated>"
|
|
869
|
+
# port = r.value
|
|
870
|
+
# port.send('test') # raise Ractor::ClosedError
|
|
871
|
+
#
|
|
872
|
+
# If the `obj` is unshareable, by default it will be copied into the receiving
|
|
873
|
+
# ractor by deep cloning.
|
|
874
|
+
#
|
|
875
|
+
# If the object is shareable, a reference to the object will be sent to the
|
|
876
|
+
# receiving ractor.
|
|
877
|
+
#
|
|
878
|
+
def send: (T obj, ?move: boolish) -> self
|
|
879
|
+
|
|
880
|
+
private
|
|
881
|
+
|
|
882
|
+
# <!--
|
|
883
|
+
# rdoc-file=ractor_sync.c
|
|
884
|
+
# - Ractor::Port.new -> new_port
|
|
885
|
+
# -->
|
|
886
|
+
# Returns a new Ractor::Port object.
|
|
887
|
+
#
|
|
888
|
+
def initialize: () -> void
|
|
889
|
+
|
|
890
|
+
def initialize_copy: (untyped) -> untyped
|
|
891
|
+
end
|
|
892
|
+
|
|
1040
893
|
# <!-- rdoc-file=ractor.c -->
|
|
1041
|
-
# Raised on
|
|
1042
|
-
# Ractor. Its `cause` will contain the original exception, and `ractor` is
|
|
1043
|
-
# original ractor it was raised in.
|
|
894
|
+
# Raised on Ractor#join or Ractor#value if there was an uncaught exception in
|
|
895
|
+
# the Ractor. Its `cause` will contain the original exception, and `ractor` is
|
|
896
|
+
# the original ractor it was raised in.
|
|
1044
897
|
#
|
|
1045
898
|
# r = Ractor.new { raise "Something weird happened" }
|
|
1046
899
|
#
|
|
1047
900
|
# begin
|
|
1048
|
-
# r.
|
|
901
|
+
# r.value
|
|
1049
902
|
# rescue => e
|
|
1050
903
|
# p e # => #<Ractor::RemoteError: thrown by remote Ractor.>
|
|
1051
904
|
# p e.ractor == r # => true
|
|
@@ -1054,11 +907,14 @@ class Ractor
|
|
|
1054
907
|
#
|
|
1055
908
|
class RemoteError < Ractor::Error
|
|
1056
909
|
# <!-- rdoc-file=ractor.rb -->
|
|
1057
|
-
# The Ractor
|
|
910
|
+
# The Ractor in which the uncaught exception was raised.
|
|
1058
911
|
#
|
|
1059
912
|
def ractor: () -> Ractor
|
|
1060
913
|
end
|
|
1061
914
|
|
|
915
|
+
# <!-- rdoc-file=ractor.c -->
|
|
916
|
+
# Raised when Ractor-unsafe C-methods is invoked by a non-main Ractor.
|
|
917
|
+
#
|
|
1062
918
|
class UnsafeError < Ractor::Error
|
|
1063
919
|
end
|
|
1064
920
|
|