core/ractor.rbs in rbs-2.0.0 vs core/ractor.rbs in rbs-2.1.0

- old
+ new

@@ -1,17 +1,18 @@ +# <!-- rdoc-file=ractor.rb --> # Ractor is a Actor-model abstraction for Ruby that provides thread-safe # parallel execution. # -# Ractor.new can make new Ractor and it will run in parallel. +# Ractor.new can make a new Ractor, and it will run in parallel. # # # The simplest ractor # r = Ractor.new {puts "I am in Ractor!"} -# r.take # wait it to finish +# r.take # wait for it to finish # # here "I am in Ractor!" would be printed # -# Ractors do not share usual objects, so the some kind of thread-safety concerns -# such as data-race, race-conditions are not available on multi-ractor +# 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. # # 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. @@ -154,11 +155,11 @@ # # 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 definitons are shared between ractors. +# 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. # We can not define mutable shareable objects in Ruby, but C extensions can # introduce them. # @@ -204,11 +205,11 @@ # r.take # # I see C # # can not access instance variables of classes/modules from non-main Ractors (RuntimeError) # # See also the description of `# shareable_constant_value` pragma in [Comments -# syntax](rdoc-ref:doc/syntax/comments.rdoc) explanation. +# 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). @@ -233,12 +234,17 @@ # 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. # # ## Reference # -# See [Ractor desgin doc](rdoc-ref:doc/ractor.md) for more details. +# 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. # # Ractor.count #=> 1 # r = Ractor.new(name: 'example') { Ractor.yield(1) } # Ractor.count #=> 2 (main + example ractor) @@ -246,20 +252,32 @@ # r.take # wait till r will finish # Ractor.count #=> 1 # def self.count: () -> Integer + # <!-- + # rdoc-file=ractor.rb + # - current() + # --> # Returns the currently executing Ractor. # # Ractor.current #=> #<Ractor:#1 running> # def self.current: () -> untyped + # <!-- + # rdoc-file=ractor.rb + # - main() + # --> # returns main ractor # def self.main: () -> untyped + # <!-- + # rdoc-file=ractor.rb + # - Ractor.make_shareable(obj, copy: false) -> shareable_obj + # --> # Make `obj` shareable between ractors. # # `obj` and all the objects it refers to will be frozen, unless they are already # shareable. # @@ -291,10 +309,14 @@ # See also the "Shareable and unshareable objects" section in the Ractor class # docs. # def self.make_shareable: [T] (T obj, ?copy: boolish) -> T + # <!-- + # 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. # @@ -322,10 +344,14 @@ # 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. # # r = Ractor.new do # v1 = Ractor.receive @@ -380,10 +406,14 @@ # wait # # in `receive': The incoming port is already closed => #<Ractor:#2 test.rb:1 running> (Ractor::ClosedError) # def self.receive: () -> untyped + # <!-- + # 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. # @@ -402,11 +432,11 @@ # foo3 # bar1 # baz2 # # If the block returns a truthy value, the message will be removed from the - # incoming queue and returned. Otherwise, the messsage remains in the incoming + # incoming queue and returned. Otherwise, the message remains in the incoming # queue and the following received 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. # @@ -437,12 +467,21 @@ # Ractor.receive_if{|msg| Ractor.receive} # #=> `receive': can not call receive/receive_if recursively (Ractor::Error) # def self.receive_if: () { (untyped) -> boolish } -> untyped + # <!-- + # rdoc-file=ractor.rb + # - recv() + # --> + # alias self.recv self.receive + # <!-- + # 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. # # r1 = Ractor.new {Ractor.yield 'from 1'} # r2 = Ractor.new {Ractor.yield 'from 2'} @@ -486,12 +525,16 @@ # Received nil from :yield # # `move` boolean flag defines whether yielded value should be copied (default) # or moved. # - def self.select: (*Ractor ractors, ?move: boolish, ?yield_value: untyped) -> [Ractor | Symbol, untyped] + 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'.freeze) #=> true @@ -499,10 +542,14 @@ # See also the "Shareable and unshareable objects" section in the Ractor class # docs. # def self.shareable?: (untyped obj) -> bool + # <!-- + # 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. # # r = Ractor.new {Ractor.yield 'Hello from ractor'} # puts r.take # # Prints: "Hello from ractor" @@ -537,20 +584,37 @@ # def self.yield: (untyped obj, ?move: boolish) -> untyped public + # <!-- + # rdoc-file=ractor.rb + # - <<(obj, move: false) + # --> + # alias << send + # <!-- + # rdoc-file=ractor.rb + # - [](sym) + # --> # get a value from ractor-local storage # def []: (Symbol | String sym) -> untyped + # <!-- + # rdoc-file=ractor.rb + # - []=(sym, val) + # --> # set a value in ractor-local storage # def []=: [T] (Symbol | String sym, T val) -> T + # <!-- + # 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. # # r = Ractor.new {sleep(500)} @@ -559,10 +623,14 @@ # r.send('test') # # Ractor::ClosedError (The incoming-port is already closed) # def close_incoming: () -> bool + # <!-- + # 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. # # r = Ractor.new {sleep(500)} @@ -571,16 +639,29 @@ # r.take # # Ractor::ClosedError (The outgoing-port is already closed) # def close_outgoing: () -> bool + # <!-- + # rdoc-file=ractor.rb + # - inspect() + # --> + # def inspect: () -> String + # <!-- + # rdoc-file=ractor.rb + # - name() + # --> # The name set in Ractor.new, or `nil`. # def name: () -> String? + # <!-- + # 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. # # r = Ractor.new do # value = Ractor.receive # puts "Received #{value}" @@ -658,10 +739,14 @@ # r.send(s, move: true) # s.inspect #=> "message", still available # def send: (untyped obj, ?move: boolish) -> Ractor + # <!-- + # 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. # # r = Ractor.new do # Ractor.yield 'explicit yield' @@ -720,55 +805,193 @@ # Received: finishing # Continue successfully # def take: () -> untyped + # <!-- + # rdoc-file=ractor.rb + # - to_s() + # --> + # alias to_s inspect private + # <!-- + # rdoc-file=ractor.rb + # - receive() + # --> # same as Ractor.receive # def receive: () -> untyped + # <!-- + # rdoc-file=ractor.rb + # - receive_if(&b) + # --> + # def receive_if: () { (untyped) -> boolish } -> untyped + # <!-- + # rdoc-file=ractor.rb + # - recv() + # --> + # alias recv receive + # <!-- rdoc-file=ractor.c --> + # Raised when an attempt is made to send a message to a closed port, or to + # retrieve a message from a closed and empty port. Ports may be closed + # explicitly with Ractor#close_outgoing/close_incoming and are closed implicitly + # when a Ractor terminates. + # + # r = Ractor.new { sleep(500) } + # r.close_outgoing + # r.take # Ractor::ClosedError + # + # ClosedError is a descendant of StopIteration, so the closing of the ractor + # will break the loops without propagating the error: + # + # r = Ractor.new do + # loop do + # msg = receive # raises ClosedError and loop traps it + # puts "Received: #{msg}" + # end + # puts "loop exited" + # end + # + # 3.times{|i| r << i} + # r.close_incoming + # r.take + # puts "Continue successfully" + # + # This will print: + # + # Received: 0 + # Received: 1 + # Received: 2 + # loop exited + # Continue successfully + # class ClosedError < StopIteration end class Error < RuntimeError end class IsolationError < Ractor::Error end + # <!-- rdoc-file=ractor.c --> + # Raised on an attempt to access an object which was moved in Ractor#send or + # Ractor.yield. + # + # r = Ractor.new { sleep } + # + # ary = [1, 2, 3] + # r.send(ary, move: true) + # ary.inspect + # # Ractor::MovedError (can not send any methods to a moved object) + # class MovedError < Ractor::Error end + # <!-- rdoc-file=ractor.c --> + # A special object which replaces any value that was moved to another ractor in + # Ractor#send or Ractor.yield. Any attempt to access the object results in + # Ractor::MovedError. + # + # r = Ractor.new { receive } + # + # ary = [1, 2, 3] + # r.send(ary, move: true) + # p Ractor::MovedObject === ary + # # => true + # ary.inspect + # # Ractor::MovedError (can not send any methods to a moved object) + # class MovedObject < BasicObject public + # <!-- + # rdoc-file=ractor.c + # - !(*args) + # --> + # def !: (*untyped) -> untyped + # <!-- + # rdoc-file=ractor.c + # - !=(*args) + # --> + # def !=: (*untyped) -> untyped + # <!-- + # rdoc-file=ractor.c + # - ==(*args) + # --> + # def ==: (*untyped) -> untyped + # <!-- + # rdoc-file=ractor.c + # - __id__(*args) + # --> + # def __id__: (*untyped) -> untyped + # <!-- + # rdoc-file=ractor.c + # - __send__(*args) + # --> + # def __send__: (*untyped) -> untyped + # <!-- + # rdoc-file=ractor.c + # - equal?(*args) + # --> + # def equal?: (*untyped) -> untyped + # <!-- + # rdoc-file=ractor.c + # - instance_eval(*args) + # --> + # def instance_eval: (*untyped) -> untyped + # <!-- + # rdoc-file=ractor.c + # - instance_exec(*args) + # --> + # def instance_exec: (*untyped) -> untyped + # <!-- + # rdoc-file=ractor.c + # - method_missing(*args) + # --> + # def method_missing: (*untyped) -> untyped end + # <!-- rdoc-file=ractor.c --> + # Raised on attempt to Ractor#take if there was an uncaught exception in the + # Ractor. Its `cause` will contain the original exception, and `ractor` is the + # original ractor it was raised in. + # + # r = Ractor.new { raise "Something weird happened" } + # + # begin + # r.take + # rescue => e + # p e # => #<Ractor::RemoteError: thrown by remote Ractor.> + # p e.ractor == r # => true + # p e.cause # => #<RuntimeError: Something weird happened> + # end + # class RemoteError < Ractor::Error public def ractor: () -> Ractor end