65 Commits
Author SHA1 Message Date
Luke Gruber 481f16f3f1 [DOC] Improve ractor class docs (grammar, code examples) (#15686) 2025-12-22 13:22:01 -05:00
John Hawthorn 0c4fcdff32 Update ArgumentError message for Ractor.select 2025-12-18 16:47:35 -08:00
John Hawthorn 535233c68c [DOC] Update ractor.rb docs 2025-12-18 15:59:49 -08:00
Luke Gruber a7eb1879ad [DOC] small improvements to ractor class docs (#15584)
* Ractor.yield no longer exists
* Ractor.shareable_proc returns a copy of the given proc
* Improve wording for monitoring/unmonitoring ports
2025-12-18 15:08:36 -05:00
John Hawthorn 5828872ec4 Update Ractor warning message
Although the Ractor API is still experimental and may change, and there
may be some implementation issues, we should no longer say that there
are many.

Hopefully we can remove this warning entirely for Ruby 4.1
2025-12-10 16:01:27 -08:00
Koichi Sasada 2aaea665bb fix typo s/sharable/shareable/ 2025-12-05 03:10:50 +09:00
Koichi Sasada f8231dacd5 Ractor.store_if_absent should not warn
```ruby
$VERBOSE = true

Ractor.store_if_absent :key do
end #=> warning: the block passed to 'Ractor.store_if_absent' defined at <internal:ractor>:474 may be ignored
```
2025-12-04 17:15:42 +09:00
Koichi Sasada 55b1ba3bf2 Ractor.shareable_proc
call-seq:
  Ractor.sharable_proc(self: nil){} -> sharable proc

It returns shareable Proc object. The Proc object is
shareable and the self in a block will be replaced with
the value passed via `self:` keyword.

In a shareable Proc, the outer variables should
* (1) refer shareable objects
* (2) be not be overwritten

```ruby
  a = 42
  Ractor.shareable_proc{ p a }
  #=> OK

  b = 43
  Ractor.shareable_proc{ p b; b = 44 }
  #=> Ractor::IsolationError because 'b' is reassigned in the block.

  c = 44
  Ractor.shareable_proc{ p c }
  #=> Ractor::IsolationError because 'c' will be reassigned outside of the block.
  c = 45

  d = 45
  d = 46 if cond
  Ractor.shareable_proc{ p d }
  #=> Ractor::IsolationError because 'd' was reassigned outside of the block.
```

The last `d`'s case can be relaxed in a future version.

The above check will be done in a static analysis at compile time,
so the reflection feature such as `Binding#local_varaible_set`
can not be detected.

```ruby
  e = 42
  shpr = Ractor.shareable_proc{ p e } #=> OK
  binding.local_variable_set(:e, 43)
  shpr.call #=> 42 (returns captured timing value)
```

Ractor.sharaeble_lambda is also introduced.
[Feature #21550]
[Feature #21557]
2025-09-24 03:59:03 +09:00
Koichi Sasada f9bffff3d4 remove Ractor#take
[Feature #21262]
2025-09-01 17:34:41 +09:00
Nobuyoshi Nakada 6179cc0118 [DOC] Fill undocumented documents 2025-08-04 02:23:43 +09:00
Koichi Sasada 84253ce38c fix obsolete doc with Ractor::Port 2025-07-17 12:13:33 +09:00
zzak e8094943a4 s/sned/send 2025-06-09 16:23:08 +09:00
Koichi Sasada 8070d5d97d Ractor#take and warn
`Ractor#take` was deprecated but some libraries can use it as
an alias for `Ractor#value` (i.e., to wait for a Ractor's
temrination and retrieve its result).
Therefore `Ractor#take` is simply an alias for `Ractor#value`.

This method will remain available until the end of August 2025,
unless there is further discussion.
2025-06-04 19:18:16 +09:00
Koichi Sasada ef2bb61018 Ractor::Port
* Added `Ractor::Port`
  * `Ractor::Port#receive` (support multi-threads)
  * `Rcator::Port#close`
  * `Ractor::Port#closed?`
* Added some methods
  * `Ractor#join`
  * `Ractor#value`
  * `Ractor#monitor`
  * `Ractor#unmonitor`
* Removed some methods
  * `Ractor#take`
  * `Ractor.yield`
* Change the spec
  * `Racotr.select`

You can wait for multiple sequences of messages with `Ractor::Port`.

```ruby
ports = 3.times.map{ Ractor::Port.new }
ports.map.with_index do |port, ri|
  Ractor.new port,ri do |port, ri|
    3.times{|i| port << "r#{ri}-#{i}"}
  end
end

p ports.each{|port| pp 3.times.map{port.receive}}

```

In this example, we use 3 ports, and 3 Ractors send messages to them respectively.
We can receive a series of messages from each port.

You can use `Ractor#value` to get the last value of a Ractor's block:

```ruby
result = Ractor.new do
  heavy_task()
end.value
```

You can wait for the termination of a Ractor with `Ractor#join` like this:

```ruby
Ractor.new do
  some_task()
end.join
```

`#value` and `#join` are similar to `Thread#value` and `Thread#join`.

To implement `#join`, `Ractor#monitor` (and `Ractor#unmonitor`) is introduced.

This commit changes `Ractor.select()` method.
It now only accepts ports or Ractors, and returns when a port receives a message or a Ractor terminates.

We removes `Ractor.yield` and `Ractor#take` because:
* `Ractor::Port` supports most of similar use cases in a simpler manner.
* Removing them significantly simplifies the code.

We also change the internal thread scheduler code (thread_pthread.c):
* During barrier synchronization, we keep the `ractor_sched` lock to avoid deadlocks.
  This lock is released by `rb_ractor_sched_barrier_end()`
  which is called at the end of operations that require the barrier.
* fix potential deadlock issues by checking interrupts just before setting UBF.

https://bugs.ruby-lang.org/issues/21262
2025-05-31 04:01:33 +09:00
lukeg c941fced21 Throw RuntimeError if getting/setting ractor local storage for non-main ractor
[Bug #19367]
2025-05-13 13:18:10 +02:00
Kanstantsin Shautsou 4646ab8917 Use correct warn method 2025-04-07 16:37:39 +02:00
Lorenzo Zabot a203603be0 Correct typo in Ractor comment 2025-03-31 09:16:18 +09:00
Nobuyoshi Nakada e433e6515e [DOC] Exclude 'Class' and 'Module' from RDoc's autolinking 2025-01-02 12:36:06 +09:00
Nobuyoshi Nakada bf878b5494 [DOC] Ractor::RemoteError 2024-12-25 13:16:28 +09:00
Victor Shepelev efe671f9d3 Properly document Ractor#require (#12389) 2024-12-21 20:05:26 +02:00
Jean Boussier 5d97c14fec FIx Ractor.main? to return true not 0
[Bug #20954]
2024-12-16 08:37:55 +01:00
Koichi Sasada e09c23433e followup 0bdb38ba6b
(forgot to amend...)
2024-12-13 17:05:58 +09:00
Koichi Sasada 0bdb38ba6b Ractor.set_if_absent(key)
to initialize ractor local storage in thread-safety.
[Feature #20875]
2024-12-13 06:22:13 +09:00
Koichi Sasada aa63699d10 support require in non-main Ractors
Many libraries should be loaded on the main ractor because of
setting constants with unshareable objects and so on.

This patch allows to call `requore` on non-main Ractors by
asking the main ractor to call `require` on it. The calling ractor
waits for the result of `require` from the main ractor.

If the `require` call failed with some reasons, an exception
objects will be deliverred from the main ractor to the calling ractor
if it is copy-able.

Same on `require_relative` and `require` by `autoload`.

Now `Ractor.new{pp obj}` works well (the first call of `pp` requires
`pp` library implicitly).

[Feature #20627]
2024-11-08 18:02:46 +09:00
Koichi Sasada 075a102c93 Ractor.[] and Ractor.[]=
`Ractor#[]/[]=` is only for accessors to the current ractor, so that
`Ractor.[]/[]=` is simpler.
[Feature #20715]
2024-11-08 18:02:46 +09:00
Koichi Sasada f0d0c030c0 Ractor.main?
to return the current ractor is the main ractor.
(== `Ractor.current == Ractor.main`)
2024-11-08 18:02:46 +09:00
Koichi Sasada c9a9b8036c remove Ractor::Selector from Ruby level
`Ractor::Selector` is not approved by Matz so remove it from
Ruby-level.

The implementation is used by `Ractor.select` so most of implementation
was remaind and calling `rb_init_ractor_selector()`, `Ractor::Selector`
will be defined. I will provide `ractor-selector` gem to try it.
2023-12-16 01:00:01 +09:00
Koichi Sasada 5875fce6ce Ractor::Selector#empty?
It returns the waiting set is empty or not.

Also add Ractor::Selector's tests.
2023-03-03 00:08:02 +09:00
Koichi Sasada a4421bd73c Rewrite Ractor synchronization mechanism
This patch rewrites Ractor synchronization mechanism, send/receive
and take/yield.

* API
  * Ractor::Selector is introduced for lightweight waiting
    for many ractors.
* Data structure
  * remove `struct rb_ractor_waiting_list` and use
    `struct rb_ractor_queue takers_queue` to manage takers.
  * remove `rb_ractor_t::yield_atexit` and use
    `rb_ractor_t::sync::will_basket::type` to check the will.
  * add `rb_ractor_basket::p.take` to represent a taking ractor.
* Synchronization protocol
  * For the Ractor local GC, `take` can not make a copy object
    directly so ask to generate the copy from the yielding ractor.
  * The following steps shows what `r1.take` does on `r0`.
    * step1: (r0) register `r0` into `r1`'s takers.
    * step2: (r0) check `r1`'s status and wakeup r0 if `r1` is waiting
             for yielding a value.
    * step3: (r0) sleep until `r1` wakes up `r0`.
  * The following steps shows what `Ractor.yield(v)` on `r1`.
    * step1: (r1) check first takers of `r1` and if there is (`r0`),
             make a copy object of `v` and pass it to `r0` and
             wakes up `r0`.
    * step2: (r1) if there is no taker ractors, sleep until
             another ractor try to take.
2023-03-02 14:31:54 +09:00
John Bampton 2f7270c681 Fix spelling (#7389) 2023-02-27 09:56:06 -08:00
Luke Gruber 4ffef59bb1 [DOC] Make changes to docs in ractor.rb (#7180)
* Make changes to docs in ractor.rb

Mainly English changes to make things more clear, and to fix minor
non-idiomatic phrases. Also clarified difference between frozen and
shareable objects.

* More minor changes to Ractor docs.
2023-01-29 10:01:49 +09:00
Nobuyoshi Nakada 131c31a920 [Bug #19081] Show the caller location in warning for Ractor
The internal location in ractor.rb is not usefull at all.
```
$ ruby -e 'Ractor.new {}'
<internal:ractor>:267: warning: Ractor is experimental, ...
```
2022-10-26 19:43:14 +09:00
Felix Yan 1486ffe039 [DOC] Correct article of Ractor's introduction [ci skip] 2022-08-28 16:27:11 +09:00
Nobuyoshi Nakada 94c3d528e7 Fix conversion of rb_ractor_id() 2022-07-28 23:46:07 +09:00
Nobuyoshi Nakada a27c274f04 [DOC] Fix broken links [ci skip]
* As the "doc/" prefix is specified by the `--page-dir` option,
  remove from the rdoc references.
* Refer to the original .rdoc instead of the converted .html.
2021-09-15 14:16:14 +09:00
S-H-GAMELINKS bdd6d8746f Replace RBOOL macro 2021-09-05 23:01:27 +09:00
Ryuta Kamizono 33f2ff3bab Fix some typos by spell checker 2021-04-26 10:07:41 +09:00
Tom Chen 8187228de0 Fix ractor docs (#4048) [doc] 2021-01-10 15:39:37 -05:00
Marc-Andre Lafortune a76082f499 Add call-seq to Ractor doc; improve wording [doc] 2020-12-24 02:19:37 -05:00
nagachika 831f785068 [DOC] Fix typo in Ractor.make_shareable documentation. 2020-12-22 08:08:27 +09:00
Koichi Sasada c34c6a89cb fix ractor's doc. [ci skip] 2020-12-22 06:09:42 +09:00
Koichi Sasada d0e4ccbefc add Ractor.main
It returns main Ractor, like Thread.main.
[Feature #17418]
2020-12-22 05:54:14 +09:00
Koichi Sasada 35471a9487 add Ractor#[]/#[]= for ractor local storage
This API is similar to plain old Thread#[]/Fiber#[] interface
with symbol key.
2020-12-22 05:26:32 +09:00
Marc-Andre Lafortune 8f2031a067 Ractor#to_s as #inspect 2020-12-21 13:31:00 -05:00
Koichi Sasada 02d9524cda separate rb_ractor_pub from rb_ractor_t
separate some fields from rb_ractor_t to rb_ractor_pub and put it
at the beggining of rb_ractor_t and declare it in vm_core.h so
vm_core.h can access rb_ractor_pub fields.

Now rb_ec_ractor_hooks() is a complete inline function and no
MJIT related issue.
2020-12-22 00:03:00 +09:00
Koichi Sasada 7600f69a8e rename to rb_ractor_make_shareable_copy()
from rb_ractor_make_copy_shareable().
2020-12-21 02:21:33 +09:00
Nobuyoshi Nakada b911509a08 Adjusted indents of closing braces [ci skip] 2020-12-20 15:13:25 +09:00
Koichi Sasada 7f8108eeff fix indent 2020-12-20 04:51:00 +09:00
Victor Shepelev 1f565ac6d9 Add documentation for Ractor (#3895) 2020-12-19 13:04:40 -05:00
Nobuyoshi Nakada 5c9d6ea6b4 Strip trailing spaces [ci skip] 2020-12-19 15:34:37 +09:00