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

- old
+ new

@@ -1,72 +1,153 @@ -# Fibers are primitives for implementing light weight cooperative -# concurrency in Ruby. Basically they are a means of creating code blocks -# that can be paused and resumed, much like threads. The main difference -# is that they are never preempted and that the scheduling must be done by -# the programmer and not the VM. +# <!-- rdoc-file=cont.c --> +# Fibers are primitives for implementing light weight cooperative concurrency in +# Ruby. Basically they are a means of creating code blocks that can be paused +# and resumed, much like threads. The main difference is that they are never +# preempted and that the scheduling must be done by the programmer and not the +# VM. # -# As opposed to other stackless light weight concurrency models, each -# fiber comes with a stack. This enables the fiber to be paused from -# deeply nested function calls within the fiber block. See the ruby(1) -# manpage to configure the size of the fiber stack(s). +# As opposed to other stackless light weight concurrency models, each fiber +# comes with a stack. This enables the fiber to be paused from deeply nested +# function calls within the fiber block. See the ruby(1) manpage to configure +# the size of the fiber stack(s). # # When a fiber is created it will not run automatically. Rather it must be -# explicitly asked to run using the `Fiber#resume` method. The code -# running inside the fiber can give up control by calling `Fiber.yield` in -# which case it yields control back to caller (the caller of the -# `Fiber#resume` ). +# explicitly asked to run using the Fiber#resume method. The code running inside +# the fiber can give up control by calling Fiber.yield in which case it yields +# control back to caller (the caller of the Fiber#resume). # -# Upon yielding or termination the [Fiber](Fiber) -# returns the value of the last executed expression +# Upon yielding or termination the Fiber returns the value of the last executed +# expression # # For instance: # -# ```ruby -# fiber = Fiber.new do -# Fiber.yield 1 -# 2 -# end +# fiber = Fiber.new do +# Fiber.yield 1 +# 2 +# end # -# puts fiber.resume -# puts fiber.resume -# puts fiber.resume -# ``` +# puts fiber.resume +# puts fiber.resume +# puts fiber.resume # # *produces* # # 1 # 2 # FiberError: dead fiber called # -# The `Fiber#resume` method accepts an arbitrary number of parameters, if -# it is the first call to `resume` then they will be passed as block -# arguments. Otherwise they will be the return value of the call to -# `Fiber.yield` +# The Fiber#resume method accepts an arbitrary number of parameters, if it is +# the first call to #resume then they will be passed as block arguments. +# Otherwise they will be the return value of the call to Fiber.yield # # Example: # -# ```ruby -# fiber = Fiber.new do |first| -# second = Fiber.yield first + 2 -# end +# fiber = Fiber.new do |first| +# second = Fiber.yield first + 2 +# end # -# puts fiber.resume 10 -# puts fiber.resume 14 -# puts fiber.resume 18 -# ``` +# puts fiber.resume 10 +# puts fiber.resume 1_000_000 +# puts fiber.resume "The fiber will be dead before I can cause trouble" # # *produces* # # 12 -# 14 +# 1000000 # FiberError: dead fiber called +# +# ## Non-blocking Fibers +# +# The concept of *non-blocking fiber* was introduced in Ruby 3.0. A non-blocking +# fiber, when reaching a operation that would normally block the fiber (like +# `sleep`, or wait for another process or I/O) will yield control to other +# fibers and allow the *scheduler* to handle blocking and waking up (resuming) +# this fiber when it can proceed. +# +# For a Fiber to behave as non-blocking, it need to be created in Fiber.new with +# `blocking: false` (which is the default), and Fiber.scheduler should be set +# with Fiber.set_scheduler. If Fiber.scheduler is not set in the current thread, +# blocking and non-blocking fibers' behavior is identical. +# +# Ruby doesn't provide a scheduler class: it is expected to be implemented by +# the user and correspond to Fiber::SchedulerInterface. +# +# There is also Fiber.schedule method, which is expected to immediately perform +# the given block in a non-blocking manner. Its actual implementation is up to +# the scheduler. +# class Fiber < Object + # <!-- + # rdoc-file=cont.c + # - Fiber.yield(args, ...) -> obj + # --> + # Yields control back to the context that resumed the fiber, passing along any + # arguments that were passed to it. The fiber will resume processing at this + # point when #resume is called next. Any arguments passed to the next #resume + # will be the value that this Fiber.yield expression evaluates to. + # def self.yield: (*untyped args) -> untyped + # <!-- + # rdoc-file=cont.c + # - Fiber.new(blocking: false) { |*args| ... } -> fiber + # --> + # Creates new Fiber. Initially, the fiber is not running and can be resumed with + # #resume. Arguments to the first #resume call will be passed to the block: + # + # f = Fiber.new do |initial| + # current = initial + # loop do + # puts "current: #{current.inspect}" + # current = Fiber.yield + # end + # end + # f.resume(100) # prints: current: 100 + # f.resume(1, 2, 3) # prints: current: [1, 2, 3] + # f.resume # prints: current: nil + # # ... and so on ... + # + # If `blocking: false` is passed to `Fiber.new`, *and* current thread has a + # Fiber.scheduler defined, the Fiber becomes non-blocking (see "Non-blocking + # Fibers" section in class docs). + # def initialize: () { () -> untyped } -> void + # <!-- + # rdoc-file=cont.c + # - fiber.resume(args, ...) -> obj + # --> + # Resumes the fiber from the point at which the last Fiber.yield was called, or + # starts running it if it is the first call to #resume. Arguments passed to + # resume will be the value of the Fiber.yield expression or will be passed as + # block parameters to the fiber's block if this is the first #resume. + # + # Alternatively, when resume is called it evaluates to the arguments passed to + # the next Fiber.yield statement inside the fiber's block or to the block value + # if it runs to completion without any Fiber.yield + # def resume: (*untyped args) -> untyped + # <!-- + # rdoc-file=cont.c + # - fiber.raise -> obj + # - fiber.raise(string) -> obj + # - fiber.raise(exception [, string [, array]]) -> obj + # --> + # Raises an exception in the fiber at the point at which the last `Fiber.yield` + # was called. If the fiber has not been started or has already run to + # completion, raises `FiberError`. If the fiber is yielding, it is resumed. If + # it is transferring, it is transferred into. But if it is resuming, raises + # `FiberError`. + # + # With no arguments, raises a `RuntimeError`. With a single `String` argument, + # raises a `RuntimeError` with the string as a message. Otherwise, the first + # parameter should be the name of an `Exception` class (or an object that + # returns an `Exception` object when sent an `exception` message). The optional + # second parameter sets the message associated with the exception, and the third + # parameter is an array of callback information. Exceptions are caught by the + # `rescue` clause of `begin...end` blocks. + # def raise: () -> untyped | (string message) -> untyped | (_Exception exception, ?string message, ?Array[String] backtrace) -> untyped end