From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: AS4713 221.184.0.0/13 X-Spam-Status: No, score=-3.0 required=3.0 tests=BAYES_00,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,RCVD_IN_DNSWL_MED,RP_MATCHES_RCVD,SPF_PASS, T_DKIM_INVALID shortcircuit=no autolearn=ham autolearn_force=no version=3.4.0 Received: from neon.ruby-lang.org (neon.ruby-lang.org [221.186.184.75]) by dcvr.yhbt.net (Postfix) with ESMTP id 8311120281 for ; Fri, 15 Sep 2017 16:08:39 +0000 (UTC) Received: from neon.ruby-lang.org (localhost [IPv6:::1]) by neon.ruby-lang.org (Postfix) with ESMTP id 34E5C12091A; Sat, 16 Sep 2017 01:08:38 +0900 (JST) Received: from o1678948x4.outbound-mail.sendgrid.net (o1678948x4.outbound-mail.sendgrid.net [167.89.48.4]) by neon.ruby-lang.org (Postfix) with ESMTPS id 25FFD12091A for ; Sat, 16 Sep 2017 01:08:34 +0900 (JST) DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=sendgrid.me; h=from:to:references:subject:mime-version:content-type:content-transfer-encoding:list-id; s=smtpapi; bh=TlmYxIX1z2mPo39NmE5ELF74M24=; b=vKCt4KtQEBVqp7cp9Q Z+LEO0+cRVAZikpk2KdktzcbDl4M4LZQTLZ1Q0rObQ+OtaeuPTwdwZGuFABL2ITw IW8sh1uCCKP+TlE2nbBNnZ5qsW/5FE54o+8f2G7cUdlXTdw5VvXUcmVhgfAk9IKR 9Fw04DGqtj07deyvEykK+eIHQ= Received: by filter0015p3mdw1.sendgrid.net with SMTP id filter0015p3mdw1-13125-59BBFB00-1F 2017-09-15 16:08:32.302167065 +0000 UTC Received: from herokuapp.com (ec2-54-224-187-163.compute-1.amazonaws.com [54.224.187.163]) by ismtpd0003p1iad1.sendgrid.net (SG) with ESMTP id DnEQpmNyS3q0hyfanBShWg Fri, 15 Sep 2017 16:08:32.183 +0000 (UTC) Date: Fri, 15 Sep 2017 16:08:32 +0000 (UTC) From: git@chuckremes.com To: ruby-core@ruby-lang.org Message-ID: References: Mime-Version: 1.0 X-Redmine-MailingListIntegration-Message-Ids: 57906 X-Redmine-Project: ruby-trunk X-Redmine-Issue-Id: 13821 X-Redmine-Issue-Author: cremes X-Redmine-Sender: cremes X-Mailer: Redmine X-Redmine-Host: bugs.ruby-lang.org X-Redmine-Site: Ruby Issue Tracking System X-Auto-Response-Suppress: All Auto-Submitted: auto-generated X-SG-EID: ync6xU2WACa70kv/Ymy4QrNMhiuLXJG8OTL2vJD1yS5rKhNqAi1U7NNaQK9jVoIuEti8vFXNghoNTs 2iysbD9I5+KRp5F+PbJSLeFn6y5FuLJWdgvrksgXqYZpK0D4IkE8gQVrD3qLRWwZ3httYU1liCUrkv Ovr0AOM00k+oq4TWBkFY2tcUeIDBq4/DI0UHxQ3VLgbvQgHiLi5V3SbrbA== X-ML-Name: ruby-core X-Mail-Count: 82818 Subject: [ruby-core:82818] [Ruby trunk Feature#13821] Allow fibers to be resumed across threads X-BeenThere: ruby-core@ruby-lang.org X-Mailman-Version: 2.1.15 Precedence: list Reply-To: Ruby developers List-Id: Ruby developers List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ruby-core-bounces@ruby-lang.org Sender: "ruby-core" Issue #13821 has been updated by cremes (Chuck Remes). I took a look at the C++ Boost library boost::fiber documentation. It allows fibers to be detached/attached between threads. Perhaps an explicit API like this is a better approach? See here: http://www.boost.org/doc/libs/1_62_0/libs/fiber/doc/html/fiber/migration.html This puts the responsibility onto the programmer to Fiber#detach from its current thread and Fiber#attach(thread) to a new thread. The limitation is that a Fiber cannot be moved if it is *blocked* or if it is currently running. By making the detach/attach explicit, then the programmer is assuming 100% responsibility to make sure the fiber hasn't yielded while holding locks or other operations that assume the Fiber is locked to a thread. ---------------------------------------- Feature #13821: Allow fibers to be resumed across threads https://bugs.ruby-lang.org/issues/13821#change-66696 * Author: cremes (Chuck Remes) * Status: Open * Priority: Normal * Assignee: * 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/