ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
From: shannonskipper@gmail.com
To: ruby-core@ruby-lang.org
Subject: [ruby-core:91302] [Ruby trunk Feature#13821] Allow fibers to be resumed across threads
Date: Sun, 27 Jan 2019 20:28:12 +0000 (UTC)	[thread overview]
Message-ID: <redmine.journal-76548.20190127202810.884c410d74cb6b02@ruby-lang.org> (raw)
In-Reply-To: redmine.issue-13821.20170816171949@ruby-lang.org

Issue #13821 has been updated by shan (Shannon Skipper).


bascule (Tony Arcieri) wrote:
> There's a simple solution to this: track if a given fiber is holding mutexes (e.g. keep a count of them) and if it is, make Fiber#resume raise an exception if it is resumed in a different thread from the one where it was originally yielded.

I'd love this. I've been frustrated by not being able to share simple Enumerators across Threads.

----------------------------------------
Feature #13821: Allow fibers to be resumed across threads
https://bugs.ruby-lang.org/issues/13821#change-76548

* Author: cremes (Chuck Remes)
* Status: Assigned
* Priority: Normal
* Assignee: ko1 (Koichi Sasada)
* Target version: 
----------------------------------------
Given a Fiber created in ThreadA, Ruby 2.4.1 (and earlier releases) raise a FiberError if the fiber is resumed in ThreadB or any other thread other than the one that created the original Fiber.

Sample code attached to demonstrate problem.

If Fibers are truly encapsulating all of the data for the continuation, we should be allowed to move them between Threads and resume their operation.

Why?

One use-case is to support the async-await asynchronous programming model. In that model, a method marked async runs *synchronously* until the #await method is encountered. At that point the method is suspended and control is returned to the caller. When the #await method completes (asynchronously) then it may resume the suspended method and continue. The only way to capture this program state, suspend and resume, is via a Fiber.

example:

```
class Wait
  include AsyncAwait

  def dofirst
    async do
      puts 'Synchronously print dofirst.'
      result = await { dosecond }
      puts 'dosecond is complete'
      result
    end
  end

  def dosecond
    async do
      puts 'Synchronously print dosecond from async task.'
      slept = await { sleep 3 }
      puts 'Sleep complete'
      slept
    end
  end

  def run
    task = dofirst
    puts 'Received task'
    p AsyncAwait::Task.await(task)
  end
end

Wait.new.run
```
```
# Expected output:
# Synchronous print dofirst.
# Received task
# Synchronously print dosecond from async task.
# Sleep complete
# dosecond is complete
# 3
```
Right now the best way to accomplish suspension of the #dofirst and #dosecond commands and allow them to run asynchronously is by passing those blocks to *another thread* (other than the callers thread) so they can be encapsulated in a new Fiber and then yielded. When it's time to resume after #await completes, that other thread must lookup the fiber and resume it. This is lots of extra code and logic to make sure that fibers are only resumed on the threads that created them. Allowing Fibers to migrate between threads would eliminate this problem.


---Files--------------------------------
fiber_across_threads.rb (377 Bytes)
wait.rb (728 Bytes)


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

  parent reply	other threads:[~2019-01-27 20:28 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <redmine.issue-13821.20170816171949@ruby-lang.org>
2017-08-16 17:19 ` [ruby-core:82402] [Ruby trunk Feature#13821] Allow fibers to be resumed across threads git
2017-09-05 17:43 ` [ruby-core:82659] " xkernigh
2017-09-12 12:17 ` [ruby-core:82758] " eregontp
2017-09-12 13:44 ` [ruby-core:82761] " git
2017-09-12 13:56 ` [ruby-core:82763] " git
2017-09-12 16:32 ` [ruby-core:82765] " eregontp
2017-09-15 13:40 ` [ruby-core:82814] " git
2017-09-15 16:08 ` [ruby-core:82818] " git
2017-09-25 12:41 ` [ruby-core:82994] [Ruby trunk Feature#13821][Assigned] " shyouhei
2018-02-21  6:39 ` [ruby-core:85722] [Ruby trunk Feature#13821] " ko1
2018-06-06 22:30 ` [ruby-core:87437] " bascule
2019-01-27 20:28 ` shannonskipper [this message]
2019-02-15 10:09 ` [ruby-core:91557] " shannonskipper

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.ruby-lang.org/en/community/mailing-lists/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=redmine.journal-76548.20190127202810.884c410d74cb6b02@ruby-lang.org \
    --to=ruby-core@ruby-lang.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).