core/ractor.rbs in rbs-3.3.2 vs core/ractor.rbs in rbs-3.4.0.pre.1
- old
+ new
@@ -1,120 +1,128 @@
# <!-- rdoc-file=ractor.rb -->
# Ractor is an Actor-model abstraction for Ruby that provides thread-safe
# parallel execution.
#
-# Ractor.new can make a new Ractor, and it will run in parallel.
+# Ractor.new makes a new Ractor, which can run in parallel.
#
# # The simplest ractor
# r = Ractor.new {puts "I am in Ractor!"}
# r.take # wait for it to finish
-# # here "I am in Ractor!" would be printed
+# # Here, "I am in Ractor!" is printed
#
-# Ractors do not share usual objects, so the same kinds of thread-safety
-# concerns such as data-race, race-conditions are not available on multi-ractor
-# programming.
+# Ractors do not share all objects with each other. There are two main benefits
+# to this: across ractors, thread-safety concerns such as data-races and
+# race-conditions are not possible. The other benefit is parallelism.
#
-# To achieve this, ractors severely limit object sharing between different
-# ractors. For example, unlike threads, ractors can't access each other's
-# objects, nor any objects through variables of the outer scope.
+# To achieve this, object sharing is limited across ractors. For example, unlike
+# in threads, ractors can't access all the objects available in other ractors.
+# Even objects normally available through variables in the outer scope are
+# prohibited from being used across ractors.
#
# a = 1
# r = Ractor.new {puts "I am in Ractor! a=#{a}"}
# # fails immediately with
# # ArgumentError (can not isolate a Proc because it accesses outer variables (a).)
#
+# The object must be explicitly shared:
+# a = 1
+# r = Ractor.new(a) { |a1| puts "I am in Ractor! a=#{a1}"}
+#
# On CRuby (the default implementation), Global Virtual Machine Lock (GVL) is
-# held per ractor, so ractors are performed in parallel without locking each
-# other.
+# held per ractor, so ractors can perform in parallel without locking each
+# other. This is unlike the situation with threads on CRuby.
#
-# Instead of accessing the shared state, the objects should be passed to and
-# from ractors via sending and receiving objects as messages.
+# Instead of accessing shared state, objects should be passed to and from
+# ractors by sending and receiving them as messages.
#
# a = 1
# r = Ractor.new do
-# a_in_ractor = receive # receive blocks till somebody will pass message
+# a_in_ractor = receive # receive blocks until somebody passes a message
# puts "I am in Ractor! a=#{a_in_ractor}"
# end
# r.send(a) # pass it
# r.take
-# # here "I am in Ractor! a=1" would be printed
+# # Here, "I am in Ractor! a=1" is printed
#
# There are two pairs of methods for sending/receiving messages:
#
# * Ractor#send and Ractor.receive for when the *sender* knows the receiver
# (push);
# * Ractor.yield and Ractor#take for when the *receiver* knows the sender
# (pull);
#
#
-# In addition to that, an argument to Ractor.new would be passed to block and
-# available there as if received by Ractor.receive, and the last block value
-# would be sent outside of the ractor as if sent by Ractor.yield.
+# In addition to that, any arguments passed to Ractor.new are passed to the
+# block and available there as if received by Ractor.receive, and the last block
+# value is sent outside of the ractor as if sent by Ractor.yield.
#
-# A little demonstration on a classic ping-pong:
+# A little demonstration of a classic ping-pong:
#
-# server = Ractor.new do
+# server = Ractor.new(name: "server") do
# puts "Server starts: #{self.inspect}"
# puts "Server sends: ping"
# Ractor.yield 'ping' # The server doesn't know the receiver and sends to whoever interested
# received = Ractor.receive # The server doesn't know the sender and receives from whoever sent
# puts "Server received: #{received}"
# end
#
-# client = Ractor.new(server) do |srv| # The server is sent inside client, and available as srv
+# client = Ractor.new(server) do |srv| # The server is sent to the client, and available as srv
# puts "Client starts: #{self.inspect}"
-# received = srv.take # The Client takes a message specifically from the server
+# received = srv.take # The client takes a message from the server
# puts "Client received from " \
# "#{srv.inspect}: #{received}"
# puts "Client sends to " \
# "#{srv.inspect}: pong"
-# srv.send 'pong' # The client sends a message specifically to the server
+# srv.send 'pong' # The client sends a message to the server
# end
#
-# [client, server].each(&:take) # Wait till they both finish
+# [client, server].each(&:take) # Wait until they both finish
#
-# This will output:
+# This will output something like:
#
-# Server starts: #<Ractor:#2 test.rb:1 running>
+# Server starts: #<Ractor:#2 server test.rb:1 running>
# Server sends: ping
# Client starts: #<Ractor:#3 test.rb:8 running>
-# Client received from #<Ractor:#2 rac.rb:1 blocking>: ping
-# Client sends to #<Ractor:#2 rac.rb:1 blocking>: pong
+# Client received from #<Ractor:#2 server test.rb:1 blocking>: ping
+# Client sends to #<Ractor:#2 server test.rb:1 blocking>: pong
# Server received: pong
#
-# It is said that Ractor receives messages via the *incoming port*, and sends
-# them to the *outgoing port*. Either one can be disabled with
-# Ractor#close_incoming and Ractor#close_outgoing respectively. If a ractor
-# terminated, its ports will be closed automatically.
+# Ractors receive their messages via the *incoming port*, and send them to the
+# *outgoing port*. Either one can be disabled with Ractor#close_incoming and
+# Ractor#close_outgoing, respectively. When a ractor terminates, its ports are
+# closed automatically.
#
# ## Shareable and unshareable objects
#
-# When the object is sent to and from the ractor, it is important to understand
-# whether the object is shareable or unshareable. Most of objects are
-# unshareable objects.
+# When an object is sent to and from a ractor, it's important to understand
+# whether the object is shareable or unshareable. Most Ruby objects are
+# unshareable objects. Even frozen objects can be unshareable if they contain
+# (through their instance variables) unfrozen objects.
#
-# Shareable objects are basically those which can be used by several threads
-# without compromising thread-safety; e.g. immutable ones. Ractor.shareable?
-# allows to check this, and Ractor.make_shareable tries to make object shareable
-# if it is not.
+# Shareable objects are those which can be used by several threads without
+# compromising thread-safety, for example numbers, `true` and `false`.
+# Ractor.shareable? allows you to check this, and Ractor.make_shareable tries to
+# make the object shareable if it's not already, and gives an error if it can't
+# do it.
#
-# Ractor.shareable?(1) #=> true -- numbers and other immutable basic values are
-# Ractor.shareable?('foo') #=> false, unless the string is frozen due to # freeze_string_literals: true
+# Ractor.shareable?(1) #=> true -- numbers and other immutable basic values are shareable
+# Ractor.shareable?('foo') #=> false, unless the string is frozen due to # frozen_string_literal: true
# Ractor.shareable?('foo'.freeze) #=> true
+# Ractor.shareable?([Object.new].freeze) #=> false, inner object is unfrozen
#
# ary = ['hello', 'world']
# ary.frozen? #=> false
# ary[0].frozen? #=> false
# Ractor.make_shareable(ary)
# ary.frozen? #=> true
# ary[0].frozen? #=> true
# ary[1].frozen? #=> true
#
# When a shareable object is sent (via #send or Ractor.yield), no additional
-# processing happens, and it just becomes usable by both ractors. When an
+# processing occurs on it. It just becomes usable by both ractors. When an
# unshareable object is sent, it can be either *copied* or *moved*. The first is
-# the default, and it makes the object's full copy by deep cloning of
+# the default, and it copies the object fully by deep cloning (Object#clone) the
# non-shareable parts of its structure.
#
# data = ['foo', 'bar'.freeze]
# r = Ractor.new do
# data2 = Ractor.receive
@@ -122,22 +130,23 @@
# end
# r.send(data)
# r.take
# puts "Outside : #{data.object_id}, #{data[0].object_id}, #{data[1].object_id}"
#
-# This will output:
+# This will output something like:
#
# In ractor: 340, 360, 320
# Outside : 380, 400, 320
#
-# (Note that object id of both array and non-frozen string inside array have
-# changed inside the ractor, showing it is different objects. But the second
-# array's element, which is a shareable frozen string, has the same object_id.)
+# Note that the object ids of the array and the non-frozen string inside the
+# array have changed in the ractor because they are different objects. The
+# second array's element, which is a shareable frozen string, is the same
+# object.
#
-# Deep cloning of the objects may be slow, and sometimes impossible.
-# Alternatively, `move: true` may be used on sending. This will *move* the
-# object to the receiving ractor, making it inaccessible for a sending ractor.
+# Deep cloning of objects may be slow, and sometimes impossible. Alternatively,
+# `move: true` may be used during sending. This will *move* the unshareable
+# object to the receiving ractor, making it inaccessible to the sending ractor.
#
# data = ['foo', 'bar']
# r = Ractor.new do
# data_in_ractor = Ractor.receive
# puts "In ractor: #{data_in_ractor.object_id}, #{data_in_ractor[0].object_id}"
@@ -154,41 +163,44 @@
# test.rb:9:in `method_missing': can not send any methods to a moved object (Ractor::MovedError)
#
# Notice that even `inspect` (and more basic methods like `__id__`) is
# inaccessible on a moved object.
#
-# Besides frozen objects, there are shareable objects. Class and Module objects
-# are shareable so the Class/Module definitions are shared between ractors.
-# Ractor objects are also shareable objects. All operations for the shareable
-# mutable objects are thread-safe, so the thread-safety property will be kept.
+# Class and Module objects are shareable so the class/module definitions are
+# shared between ractors. Ractor objects are also shareable. All operations on
+# shareable objects are thread-safe, so the thread-safety property will be kept.
# We can not define mutable shareable objects in Ruby, but C extensions can
# introduce them.
#
-# It is prohibited to access instance variables of mutable shareable objects
-# (especially Modules and classes) from ractors other than main:
+# It is prohibited to access (get) instance variables of shareable objects in
+# other ractors if the values of the variables aren't shareable. This can occur
+# because modules/classes are shareable, but they can have instance variables
+# whose values are not. In non-main ractors, it's also prohibited to set
+# instance variables on classes/modules (even if the value is shareable).
#
# class C
# class << self
# attr_accessor :tricky
# end
# end
#
-# C.tricky = 'test'
+# C.tricky = "unshareable".dup
#
# r = Ractor.new(C) do |cls|
# puts "I see #{cls}"
# puts "I can't see #{cls.tricky}"
+# cls.tricky = true # doesn't get here, but this would also raise an error
# end
# r.take
# # I see C
# # can not access instance variables of classes/modules from non-main Ractors (RuntimeError)
#
# Ractors can access constants if they are shareable. The main Ractor is the
# only one that can access non-shareable constants.
#
# GOOD = 'good'.freeze
-# BAD = 'bad'
+# BAD = 'bad'.dup
#
# r = Ractor.new do
# puts "GOOD=#{GOOD}"
# puts "BAD=#{BAD}"
# end
@@ -209,49 +221,48 @@
# See also the description of `# shareable_constant_value` pragma in [Comments
# syntax](rdoc-ref:syntax/comments.rdoc) explanation.
#
# ## Ractors vs threads
#
-# Each ractor creates its own thread. New threads can be created from inside
-# ractor (and, on CRuby, sharing GVL with other threads of this ractor).
+# Each ractor has its own main Thread. New threads can be created from inside
+# ractors (and, on CRuby, they share the GVL with other threads of this ractor).
#
# r = Ractor.new do
# a = 1
# Thread.new {puts "Thread in ractor: a=#{a}"}.join
# end
# r.take
# # Here "Thread in ractor: a=1" will be printed
#
# ## Note on code examples
#
-# In examples below, sometimes we use the following method to wait till ractors
-# that are not currently blocked will finish (or process till next blocking)
-# method.
+# In the examples below, sometimes we use the following method to wait for
+# ractors that are not currently blocked to finish (or to make progress).
#
# def wait
# sleep(0.1)
# end
#
# It is **only for demonstration purposes** and shouldn't be used in a real
-# code. Most of the times, just #take is used to wait till ractor will finish.
+# code. Most of the time, #take is used to wait for ractors to finish.
#
# ## Reference
#
# See [Ractor design doc](rdoc-ref:ractor.md) for more details.
#
class Ractor
# <!--
# rdoc-file=ractor.rb
# - count()
# -->
- # Returns total count of Ractors currently running.
+ # Returns the number of Ractors currently running or blocking (waiting).
#
# Ractor.count #=> 1
# r = Ractor.new(name: 'example') { Ractor.yield(1) }
# Ractor.count #=> 2 (main + example ractor)
# r.take # wait for Ractor.yield(1)
- # r.take # wait till r will finish
+ # r.take # wait until r will finish
# Ractor.count #=> 1
#
def self.count: () -> Integer
# <!--
@@ -279,12 +290,12 @@
# Make `obj` shareable between ractors.
#
# `obj` and all the objects it refers to will be frozen, unless they are already
# shareable.
#
- # If `copy` keyword is `true`, the method will copy objects before freezing them
- # This is safer option but it can take be slower.
+ # If `copy` keyword is `true`, it will copy objects before freezing them, and
+ # will not modify `obj` or its internal objects.
#
# Note that the specification and implementation of this method are not mature
# and may be changed in the future.
#
# obj = ['test']
@@ -315,20 +326,20 @@
# rdoc-file=ractor.rb
# - Ractor.new(*args, name: nil) {|*args| block } -> ractor
# -->
# Create a new Ractor with args and a block.
#
- # A block (Proc) will be isolated (can't access to outer variables). `self`
- # inside the block will refer to the current Ractor.
+ # The given block (Proc) will be isolated (can't access any outer variables).
+ # `self` inside the block will refer to the current Ractor.
#
# r = Ractor.new { puts "Hi, I am #{self.inspect}" }
# r.take
# # Prints "Hi, I am #<Ractor:#2 test.rb:1 running>"
#
- # `args` passed to the method would be propagated to block args by the same
- # rules as objects passed through #send/Ractor.receive: if `args` are not
- # shareable, they will be copied (via deep cloning, which might be inefficient).
+ # Any `args` passed are propagated to the block arguments by the same rules as
+ # objects sent via #send/Ractor.receive. If an argument in `args` is not
+ # shareable, it will be copied (via deep cloning, which might be inefficient).
#
# arg = [1, 2, 3]
# puts "Passing: #{arg} (##{arg.object_id})"
# r = Ractor.new(arg) {|received_arg|
# puts "Received: #{received_arg} (##{received_arg.object_id})"
@@ -338,40 +349,40 @@
# # Passing: [1, 2, 3] (#280)
# # Received: [1, 2, 3] (#300)
#
# Ractor's `name` can be set for debugging purposes:
#
- # r = Ractor.new(name: 'my ractor') {}
+ # r = Ractor.new(name: 'my ractor') {}; r.take
# p r
# #=> #<Ractor:#3 my ractor test.rb:1 terminated>
#
def self.new: (*untyped args, ?name: string) { (*untyped) -> untyped } -> Ractor
# <!--
# rdoc-file=ractor.rb
# - Ractor.receive -> msg
# -->
- # Receive an incoming message from the current Ractor's incoming port's queue,
- # which was sent there by #send.
+ # Receive a message from the incoming port of the current ractor (which was sent
+ # there by #send from another ractor).
#
# r = Ractor.new do
# v1 = Ractor.receive
# puts "Received: #{v1}"
# end
# r.send('message1')
# r.take
# # Here will be printed: "Received: message1"
#
- # Alternatively, private instance method `receive` may be used:
+ # Alternatively, the private instance method `receive` may be used:
#
# r = Ractor.new do
# v1 = receive
# puts "Received: #{v1}"
# end
# r.send('message1')
# r.take
- # # Here will be printed: "Received: message1"
+ # # This prints: "Received: message1"
#
# The method blocks if the queue is empty.
#
# r = Ractor.new do
# puts "Before first receive"
@@ -395,11 +406,11 @@
# Received: message1
# Still received only one
# Received: message2
#
# If close_incoming was called on the ractor, the method raises
- # Ractor::ClosedError if there are no more messages in incoming queue:
+ # Ractor::ClosedError if there are no more messages in the incoming queue:
#
# Ractor.new do
# close_incoming
# receive
# end
@@ -412,12 +423,13 @@
# rdoc-file=ractor.rb
# - Ractor.receive_if {|msg| block } -> msg
# -->
# Receive only a specific message.
#
- # Instead of Ractor.receive, Ractor.receive_if can provide a pattern by a block
- # and you can choose the receiving message.
+ # Instead of Ractor.receive, Ractor.receive_if can be given a pattern (or any
+ # filter) in a block and you can choose the messages to accept that are
+ # available in your ractor's incoming queue.
#
# r = Ractor.new do
# p Ractor.receive_if{|msg| msg.match?(/foo/)} #=> "foo3"
# p Ractor.receive_if{|msg| msg.match?(/bar/)} #=> "bar1"
# p Ractor.receive_if{|msg| msg.match?(/baz/)} #=> "baz2"
@@ -431,13 +443,13 @@
#
# foo3
# bar1
# baz2
#
- # If the block returns a truthy value, the message will be removed from the
- # incoming queue and returned. Otherwise, the message remains in the incoming
- # queue and the following received messages are checked by the given block.
+ # If the block returns a truthy value, the message is removed from the incoming
+ # queue and returned. Otherwise, the message remains in the incoming queue and
+ # the next messages are checked by the given block.
#
# If there are no messages left in the incoming queue, the method will block
# until new messages arrive.
#
# If the block is escaped by break/return/exception/throw, the message is
@@ -459,11 +471,11 @@
#
# 2 non-matching sent, nothing received
# Received successfully: [1, 2, 3]
#
# Note that you can not call receive/receive_if in the given block recursively.
- # It means that you should not do any tasks in the block.
+ # You should not do any tasks in the block other than message filtration.
#
# Ractor.current << true
# Ractor.receive_if{|msg| Ractor.receive}
# #=> `receive': can not call receive/receive_if recursively (Ractor::Error)
#
@@ -478,23 +490,24 @@
# <!--
# rdoc-file=ractor.rb
# - Ractor.select(*ractors, [yield_value:, move: false]) -> [ractor or symbol, obj]
# -->
- # Waits for the first ractor to have something in its outgoing port, reads from
- # this ractor, and returns that ractor and the object received.
+ # Wait for any ractor to have something in its outgoing port, read from this
+ # ractor, and then return that ractor and the object received.
#
# r1 = Ractor.new {Ractor.yield 'from 1'}
# r2 = Ractor.new {Ractor.yield 'from 2'}
#
# r, obj = Ractor.select(r1, r2)
#
# puts "received #{obj.inspect} from #{r.inspect}"
# # Prints: received "from 1" from #<Ractor:#2 test.rb:1 running>
+ # # But could just as well print "from r2" here, either prints could be first.
#
- # If one of the given ractors is the current ractor, and it would be selected,
- # `r` will contain `:receive` symbol instead of the ractor object.
+ # If one of the given ractors is the current ractor, and it is selected, `r`
+ # will contain the `:receive` symbol instead of the ractor object.
#
# r1 = Ractor.new(Ractor.current) do |main|
# main.send 'to main'
# Ractor.yield 'from 1'
# end
@@ -502,14 +515,14 @@
# Ractor.yield 'from 2'
# end
#
# r, obj = Ractor.select(r1, r2, Ractor.current)
# puts "received #{obj.inspect} from #{r.inspect}"
- # # Prints: received "to main" from :receive
+ # # Could print: received "to main" from :receive
#
- # If `yield_value` is provided, that value may be yielded if another Ractor is
- # calling #take. In this case, the pair `[:yield, nil]` would be returned:
+ # If `yield_value` is provided, that value may be yielded if another ractor is
+ # calling #take. In this case, the pair `[:yield, nil]` is returned:
#
# r1 = Ractor.new(Ractor.current) do |main|
# puts "Received from main: #{main.take}"
# end
#
@@ -522,23 +535,23 @@
#
# Trying to select
# Received from main: 123
# Received nil from :yield
#
- # `move` boolean flag defines whether yielded value should be copied (default)
- # or moved.
+ # `move` boolean flag defines whether yielded value will be copied (default) or
+ # moved.
#
def self.select: (*Ractor ractors, ?move: boolish, ?yield_value: untyped) -> [ Ractor | Symbol, untyped ]
# <!--
# rdoc-file=ractor.rb
# - Ractor.shareable?(obj) -> true | false
# -->
# Checks if the object is shareable by ractors.
#
# Ractor.shareable?(1) #=> true -- numbers and other immutable basic values are frozen
- # Ractor.shareable?('foo') #=> false, unless the string is frozen due to # freeze_string_literals: true
+ # Ractor.shareable?('foo') #=> false, unless the string is frozen due to # frozen_string_literal: true
# Ractor.shareable?('foo'.freeze) #=> true
#
# See also the "Shareable and unshareable objects" section in the Ractor class
# docs.
#
@@ -546,17 +559,17 @@
# <!--
# rdoc-file=ractor.rb
# - Ractor.yield(msg, move: false) -> nil
# -->
- # Send a message to the current ractor's outgoing port to be consumed by #take.
+ # Send a message to the current ractor's outgoing port to be accepted by #take.
#
# r = Ractor.new {Ractor.yield 'Hello from ractor'}
# puts r.take
# # Prints: "Hello from ractor"
#
- # The method is blocking, and will return only when somebody consumes the sent
+ # This method is blocking, and will return only when somebody consumes the sent
# message.
#
# r = Ractor.new do
# Ractor.yield 'Hello from ractor'
# puts "Ractor: after yield"
@@ -578,11 +591,11 @@
# Ractor.yield 'Hello from ractor'
# end
# wait
# # `yield': The outgoing-port is already closed (Ractor::ClosedError)
#
- # The meaning of `move` argument is the same as for #send.
+ # The meaning of the `move` argument is the same as for #send.
#
def self.yield: (untyped obj, ?move: boolish) -> untyped
public
@@ -611,13 +624,13 @@
# <!--
# rdoc-file=ractor.rb
# - ractor.close_incoming -> true | false
# -->
- # Closes the incoming port and returns its previous state. All further attempts
- # to Ractor.receive in the ractor, and #send to the ractor will fail with
- # Ractor::ClosedError.
+ # Closes the incoming port and returns whether it was already closed. All
+ # further attempts to Ractor.receive in the ractor, and #send to the ractor will
+ # fail with Ractor::ClosedError.
#
# r = Ractor.new {sleep(500)}
# r.close_incoming #=> false
# r.close_incoming #=> true
# r.send('test')
@@ -627,13 +640,13 @@
# <!--
# rdoc-file=ractor.rb
# - ractor.close_outgoing -> true | false
# -->
- # Closes the outgoing port and returns its previous state. All further attempts
- # to Ractor.yield in the ractor, and #take from the ractor will fail with
- # Ractor::ClosedError.
+ # Closes the outgoing port and returns whether it was already closed. All
+ # further attempts to Ractor.yield in the ractor, and #take from the ractor will
+ # fail with Ractor::ClosedError.
#
# r = Ractor.new {sleep(500)}
# r.close_outgoing #=> false
# r.close_outgoing #=> true
# r.take
@@ -658,11 +671,11 @@
# <!--
# rdoc-file=ractor.rb
# - ractor.send(msg, move: false) -> self
# -->
- # Send a message to a Ractor's incoming queue to be consumed by Ractor.receive.
+ # Send a message to a Ractor's incoming queue to be accepted by Ractor.receive.
#
# r = Ractor.new do
# value = Ractor.receive
# puts "Received #{value}"
# end
@@ -675,11 +688,11 @@
# r = Ractor.new {sleep(5)}
# r.send('test')
# puts "Sent successfully"
# # Prints: "Sent successfully" immediately
#
- # Attempt to send to ractor which already finished its execution will raise
+ # An attempt to send to a ractor which already finished its execution will raise
# Ractor::ClosedError.
#
# r = Ractor.new {}
# r.take
# p r
@@ -695,15 +708,15 @@
# receive
# end
# r.close_incoming
# r.send('test')
# # Ractor::ClosedError (The incoming-port is already closed)
- # # The error would be raised immediately, not when ractor will try to receive
+ # # The error is raised immediately, not when the ractor tries to receive
#
- # If the `obj` is unshareable, by default it would be copied into ractor by deep
- # cloning. If the `move: true` is passed, object is *moved* into ractor and
- # becomes inaccessible to sender.
+ # If the `obj` is unshareable, by default it will be copied into the receiving
+ # ractor by deep cloning. If `move: true` is passed, the object is *moved* into
+ # the receiving ractor and becomes inaccessible to the sender.
#
# r = Ractor.new {puts "Received: #{receive}"}
# msg = 'message'
# r.send(msg, move: true)
# r.take
@@ -712,11 +725,11 @@
# This prints:
#
# Received: message
# in `p': undefined method `inspect' for #<Ractor::MovedObject:0x000055c99b9b69b8>
#
- # All references to the object and its parts will become invalid in sender.
+ # All references to the object and its parts will become invalid to the sender.
#
# r = Ractor.new {puts "Received: #{receive}"}
# s = 'message'
# ary = [s]
# copy = ary.dup
@@ -730,11 +743,11 @@
# # => Array, it is different object
# copy[0].inspect
# # Ractor::MovedError (can not send any methods to a moved object)
# # ...but its item was still a reference to `s`, which was moved
#
- # If the object was shareable, `move: true` has no effect on it:
+ # If the object is shareable, `move: true` has no effect on it:
#
# r = Ractor.new {puts "Received: #{receive}"}
# s = 'message'.freeze
# r.send(s, move: true)
# s.inspect #=> "message", still available
@@ -743,25 +756,25 @@
# <!--
# rdoc-file=ractor.rb
# - ractor.take -> msg
# -->
- # Take a message from ractor's outgoing port, which was put there by
- # Ractor.yield or at ractor's finalization.
+ # Get a message from the ractor's outgoing port, which was put there by
+ # Ractor.yield or at ractor's termination.
#
# r = Ractor.new do
# Ractor.yield 'explicit yield'
# 'last value'
# end
# puts r.take #=> 'explicit yield'
# puts r.take #=> 'last value'
# puts r.take # Ractor::ClosedError (The outgoing-port is already closed)
#
- # The fact that the last value is also put to outgoing port means that `take`
- # can be used as some analog of Thread#join ("just wait till ractor finishes"),
- # but don't forget it will raise if somebody had already consumed everything
- # ractor have produced.
+ # The fact that the last value is also sent to the outgoing port means that
+ # `take` can be used as an analog of Thread#join ("just wait until ractor
+ # finishes"). However, it will raise if somebody has already consumed that
+ # message.
#
# If the outgoing port was closed with #close_outgoing, the method will raise
# Ractor::ClosedError.
#
# r = Ractor.new do
@@ -771,11 +784,11 @@
# r.close_outgoing
# r.take
# # Ractor::ClosedError (The outgoing-port is already closed)
# # The error would be raised immediately, not when ractor will try to receive
#
- # If an uncaught exception is raised in the Ractor, it is propagated on take as
+ # If an uncaught exception is raised in the Ractor, it is propagated by take as
# a Ractor::RemoteError.
#
# r = Ractor.new {raise "Something weird happened"}
#
# begin
@@ -784,12 +797,13 @@
# p e # => #<Ractor::RemoteError: thrown by remote Ractor.>
# p e.ractor == r # => true
# p e.cause # => #<RuntimeError: Something weird happened>
# end
#
- # Ractor::ClosedError is a descendant of StopIteration, so the closing of the
- # ractor will break the loops without propagating the error:
+ # Ractor::ClosedError is a descendant of StopIteration, so the termination of
+ # the ractor will break out of any loops that receive this message without
+ # propagating the error:
#
# r = Ractor.new do
# 3.times {|i| Ractor.yield "message #{i}"}
# "finishing"
# end
@@ -826,10 +840,11 @@
# <!--
# rdoc-file=ractor.rb
# - receive_if(&b)
# -->
+ # same as Ractor.receive_if
#
def receive_if: () { (untyped) -> boolish } -> untyped
# <!--
# rdoc-file=ractor.rb
@@ -996,7 +1011,11 @@
def ractor: () -> Ractor
end
class UnsafeError < Ractor::Error
+ end
+
+ %a{annotate:rdoc:skip}
+ class Selector
end
end