This is a Ruby tree! It shows every object from the Ruby Programming Language in a tree format.


        # Ractor < Object

(from ruby core)

Ractor is a Actor-model abstraction for Ruby that provides thread-safe
parallel execution. can make a new Ractor, and it will run in parallel.

    # The simplest ractor
    r = {puts "I am in Ractor!"}
    r.take # wait for it to finish
    # here "I am in Ractor!" would be 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.

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.

    a = 1
    r = {puts "I am in Ractor! a=#{a}"}
    # fails immediately with
    # ArgumentError (can not isolate a Proc because it accesses outer variables (a).)

On CRuby (the default implementation), Global Virtual Machine Lock (GVL)
is held per ractor, so ractors are performed in parallel without locking
each other.

Instead of accessing the shared state, the objects should be passed to
and from ractors via sending and receiving objects as messages.

    a = 1
    r = do
      a_in_ractor = receive # receive blocks till somebody will pass message
      puts "I am in Ractor! a=#{a_in_ractor}"
    r.send(a)  # pass it
    # here "I am in Ractor! a=1" would be 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 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.

A little demonstration on a classic ping-pong:

    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}"

    client = do |srv|        # The server is sent inside client, and available as srv
      puts "Client starts: #{self.inspect}"
      received = srv.take                       # The Client takes a message specifically 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

    [client, server].each(&:take)               # Wait till they both finish

This will output:

    Server starts: #<Ractor:#2 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
    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.

## 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.

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.

    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?('foo'.freeze) #=> true

    ary = ['hello', 'world']
    ary.frozen?                 #=> false
    ary[0].frozen?              #=> false
    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 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 non-shareable parts of its structure.

    data = ['foo', 'bar'.freeze]
    r = do
      data2 = Ractor.receive
      puts "In ractor: #{data2.object_id}, #{data2[0].object_id}, #{data2[1].object_id}"
    puts "Outside  : #{data.object_id}, #{data[0].object_id}, #{data[1].object_id}"

This will output:

    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

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

    data = ['foo', 'bar']
    r = do
      data_in_ractor = Ractor.receive
      puts "In ractor: #{data_in_ractor.object_id}, #{data_in_ractor[0].object_id}"
    r.send(data, move: true)
    puts "Outside: moved? #{Ractor::MovedObject === data}"
    puts "Outside: #{data.inspect}"

This will output:

    In ractor: 100, 120
    Outside: moved? true
    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. 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:

    class C
      class << self
        attr_accessor :tricky

    C.tricky = 'test'

    r = do |cls|
      puts "I see #{cls}"
      puts "I can't see #{cls.tricky}"
    # 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'

    r = do
      puts "GOOD=#{GOOD}"
      puts "BAD=#{BAD}"
    # GOOD=good
    # can not access non-shareable objects in constant Object::BAD by non-main Ractor. (NameError)

    # Consider the same C class from above

    r = do
      puts "I see #{C}"
      puts "I can't see #{C.tricky}"
    # 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: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

    r = do
      a = 1 {puts "Thread in ractor: a=#{a}"}.join
    # 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.

    def wait

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 design doc]( for more details.
# Class methods:


# Instance methods:



This is MURDOC! A Ruby documentation browser inspired by Smalltalk-80. It allows you to learn about Ruby by browsing through its class hierarchies, and see any of its methods.