diff options
author | Koichi Sasada <ko1@atdot.net> | 2023-02-24 18:46:17 +0900 |
---|---|---|
committer | Koichi Sasada <ko1@atdot.net> | 2023-03-02 14:31:54 +0900 |
commit | a4421bd73c286253311c2cdf8c78ed258f8cff44 (patch) | |
tree | 3ebec079d5ed19429148726e2f5e60597d1df988 /bootstraptest | |
parent | 1abec43b5d3290ef2229ceb64014ed91410a6381 (diff) | |
download | ruby-a4421bd73c286253311c2cdf8c78ed258f8cff44.tar.gz |
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.
Diffstat (limited to 'bootstraptest')
-rw-r--r-- | bootstraptest/test_ractor.rb | 14 |
1 files changed, 10 insertions, 4 deletions
diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb index 459ba260e9..6898edc677 100644 --- a/bootstraptest/test_ractor.rb +++ b/bootstraptest/test_ractor.rb @@ -518,9 +518,9 @@ assert_equal '[true, true, true]', %q{ end } received = [] - take = [] + taken = [] yielded = [] - until rs.empty? + until received.size == RN && taken.size == RN && yielded.size == RN r, v = Ractor.select(CR, *rs, yield_value: 'yield') case r when :receive @@ -528,11 +528,17 @@ assert_equal '[true, true, true]', %q{ when :yield yielded << v else - take << v + taken << v rs.delete r end end - [received.all?('sendyield'), yielded.all?(nil), take.all?('take')] + r = [received == ['sendyield'] * RN, + yielded == [nil] * RN, + taken == ['take'] * RN, + ] + + STDERR.puts [received, yielded, taken].inspect + r } # multiple Ractors can send to one Ractor |