[#100284] [Ruby master Bug#17211] Test failures in ruby2.7.2 and ruby3.0~preview1 — utkarsh@...

Issue #17211 has been reported by utkarsh (Utkarsh Gupta).

10 messages 2020/10/02

[#100301] [Ruby master Feature#17215] Backport for arm64 optimizations that exist for power/x86 — jaruga@...

Issue #17215 has been reported by jaruga (Jun Aruga).

10 messages 2020/10/05

[#100329] [Ruby master Bug#17220] Rails Active Job integration test fails with Ruby 3.0.0 since 2038cc6cab6ceeffef3ec3a765c70ae684f829ed — yasuo.honda@...

Issue #17220 has been reported by yahonda (Yasuo Honda).

28 messages 2020/10/07

[#100332] [Ruby master Bug#17221] Relax the Fiber#transfer's limitation — ko1@...

Issue #17221 has been reported by ko1 (Koichi Sasada).

15 messages 2020/10/07

[#100348] [Ruby master Bug#17257] Integer#pow(0, 1) returns 1, which is incorrect — universato@...

Issue #17257 has been reported by universato (Yoshimine Sato).

13 messages 2020/10/09

[#100371] [Ruby master Feature#17260] Promote pattern matching to official feature — kazuki@...

Issue #17260 has been reported by ktsj (Kazuki Tsujimoto).

10 messages 2020/10/11

[#100383] [Ruby master Feature#17261] Software transactional memory (STM) for Threads and Ractors — ko1@...

Issue #17261 has been reported by ko1 (Koichi Sasada).

14 messages 2020/10/12

[#100401] [Ruby master Bug#17263] Fiber context switch degrades with number of fibers, limit on number of fibers — ciconia@...

Issue #17263 has been reported by ciconia (Sharon Rosner).

14 messages 2020/10/15

[#100422] [CommonRuby Feature#17265] Add `Bool` module — marcandre-ruby-core@...

Issue #17265 has been reported by marcandre (Marc-Andre Lafortune).

11 messages 2020/10/19

[#100466] [Ruby master Feature#17273] shareable_constant_value pragma — ko1@...

Issue #17273 has been reported by ko1 (Koichi Sasada).

14 messages 2020/10/21

[#100471] [Ruby master Feature#17277] Make Enumerator#with_index yield row and col indices for Matrix — grzegorz.jakubiak@...

Issue #17277 has been reported by greggzst (Grzegorz Jakubiak).

8 messages 2020/10/21

[#100479] [Ruby master Feature#17278] On-demand sharing of constants for Ractor — daniel@...42.com

Issue #17278 has been reported by Dan0042 (Daniel DeLorme).

13 messages 2020/10/21

[#100534] [Ruby master Feature#17284] Shareable Proc — ko1@...

Issue #17284 has been reported by ko1 (Koichi Sasada).

16 messages 2020/10/25

[#100597] [Ruby master Feature#17288] Optimize __send__ call with a literal method name — muraken@...

Issue #17288 has been reported by mrkn (Kenta Murata).

13 messages 2020/10/27

[#100669] [Ruby master Feature#17295] Feature: Create a directory and file with Pathname#touch — get.codetriage@...

Issue #17295 has been reported by schneems (Richard Schneeman).

9 messages 2020/10/30

[#100673] [Ruby master Feature#17298] Ractor's basket communication APIs — ko1@...

Issue #17298 has been reported by ko1 (Koichi Sasada).

15 messages 2020/10/30

[#100675] [Ruby master Misc#17299] DevelopersMeeting20201120Japan — mame@...

Issue #17299 has been reported by mame (Yusuke Endoh).

11 messages 2020/10/31

[ruby-core:100354] [Ruby master Bug#17221] Relax the Fiber#transfer's limitation

From: eregontp@...
Date: 2020-10-09 20:53:42 UTC
List: ruby-core #100354
Issue #17221 has been updated by Eregon (Benoit Daloze).


I believe it's `a yielding Fiber` (the first sound in yield-ing is not a vowel sound)

----------------------------------------
Bug #17221: Relax the Fiber#transfer's limitation
https://bugs.ruby-lang.org/issues/17221#change-87965

* Author: ko1 (Koichi Sasada)
* Status: Open
* Priority: Normal
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
Using `Fiber#transfer` with `Fiber#resume` for a same Fiber is limited (once `Fiber#transfer` is called for a fiber, the fiber can not be resumed more).

```ruby
require 'fiber'
f1 = nil
f2 = Fiber.new{
  f1.transfer
}
f1 = Fiber.new{
  f2.transfer
  Fiber.yield 10
  Fiber.yield 20
}
p f1.resume #=> 10
p f1.resume #=> `resume': cannot resume transferred Fiber (FiberError)
```

This restriction was introduced to protect the resume/yield chain, but we realized that it is too much to protect the chain.

Instead of the current restriction, we introduce some other protections.

(1) can not transfer to the resuming fiber.

```ruby
require 'fiber'

root = Fiber.current
f1 = f2 = nil

f1 = Fiber.new{
  f2 = Fiber.new{
    root.transfer(10)
  }
  f2.resume
}

p f1.transfer #=> 10

# root <-----+
#  |         |
#  v         | transfer
#  f1 -> f2 -+ # resume/yield chain


# horizontal direction: resume
# vertical direction: transfer

p f1.transfer #=> attempt to transfer to a resuming fiber (FiberError)

# f1 has it's own resume/yield chain, and f1.transfer breaks the chain

# root <-----+
#  || (error)|
#  vv        |
#  f1 -> f2 -+ # resume/yield chain
```

(2) can not transfer to the yielding fiber.

```ruby
require 'fiber'

f1 = f2 = nil

f1 = Fiber.new{
  f2 = Fiber.new{
    Fiber.yield
  }
  f2.resume
  10
}

p f1.transfer #=> 10

# root 
# | ^
# | | transfer
# v |
# f1 --> f2 # resume/yield chain
#    <--

p f2.transfer #=> `transfer': attempt to transfer to an yielding fiber (FiberError)

# f2 is waiting for the resume, so the transfer is not allowed.

# root --+
# | ^    | transfer (error)
# | |    |
# v |    v
# f1 --> f2 # resume/yield chain
#    <--

```

(3) can not resume transferring fiber.

```ruby
require 'fiber'

f1 = f2 = nil

f2 = Fiber.new{
  f1.resume #=> attempt to resume the transferring fiber (FiberError)
}
f1 = Fiber.new{
  f2.transfer
}
f1.transfer

# root
# |
# v
# f1 <-+
# |    |
# v    | resume (error)
# f2 --+

# f1 seems waiting for transfer from other fibers.
```

(4) can not yield from not-resumed fiber

```
require 'fiber'

f2 = Fiber.new do
  Fiber.yield #=> `yield': attempt to yield on not resumed fiber (FiberError)
end

f1 = Fiber.new
  f2.transfer
end

p f1.transfer

#     root
#     |
#     v
#     f1
#     |
#     v
#  <- f2
#  yield to where ...? (2.7 switches to root fiber)
```

and remove current restriction. The first example works fine:

```ruby
require 'fiber'
f1 = nil
f2 = Fiber.new{
  f1.transfer
}
f1 = Fiber.new{
  f2.transfer
  Fiber.yield 10
  Fiber.yield 20
}
p f1.resume #=> 10
p f1.resume #=> 20


# root -> f1 <-+
#         |    |
#         v    |
#         f2 --+
```

The basic idea is respect *programmer's intention*.

For (1), resuming fiber should be switched by the `Fiber.yield`.
For (2), yielding fiber should be switched by the `Fiber#resume`.
For (3), transferring fiber should be switched by the `Fiber#transfer`.

Mainly (1) can keep the resume/yield chain. Also (2) and (3) makes the chain and relationships with fibers cleanly.

----

Also at the end of a transferred fiber, it had continued on root fiber.

However, if the root fiber resumed a fiber (and that fiber can resumed another fiber), this behavior also breaks the resume/yield chain.
So at the end of a transferred fiber, switch to the edge of resume chain from root fiber.
For example, root fiber resumed f1 and f1 resumed f2, transferred to f3 and f3 terminated, then continue from the fiber f2 (it was continued
from root fiber without this patch).

```ruby
require 'fiber'
f3 = Fiber.new{
  10
}
f2 = Fiber.new{
  f3.transfer + 20
}
f1 = Fiber.new{
  f2.resume
}
p f1.resume #=> 30

# without this patch:
#
# root -> f1 -> f2
#  ^             |
#  | exit        v
#  +----------- f3

# with this patch:
#
# root -> f1 -> f2 <-+  # keep resume/yield chain
#               |    |
#               v    |
#               f3 --+ exit
```

The patch is: https://github.com/ruby/ruby/pull/3636

---Files--------------------------------
clipboard-202010080257-u2lbv.png (25.5 KB)


-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>

In This Thread