rfc:fiber

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
Next revisionBoth sides next revision
rfc:fiber [2018/02/10 15:47] lvhtrfc:fiber [2018/04/18 22:36] lvht
Line 2: Line 2:
   * Version: 0.1   * Version: 0.1
   * Date: 2017-09-13   * Date: 2017-09-13
-  * Author: Haitao Lvi@lvht.net+  * Author: Haitao Lv<i@lvht.net>, Dmitry Stogov<dmitry@zend.com>, Martin Schröder<m.schroeder2007@googlemail.com>
   * Status: Under Discussion   * Status: Under Discussion
   * First Published at: http://wiki.php.net/rfc/fiber   * First Published at: http://wiki.php.net/rfc/fiber
Line 16: Line 16:
 ===== Proposal ===== ===== Proposal =====
 ==== Why not make it as a Extension? ==== ==== Why not make it as a Extension? ====
 +Fiber is a major language feature, that allows significant benefits for asynchronous frameworks. Providing it as an optional extension, just doesn't make sense.
 +
 ==== Implementation ==== ==== Implementation ====
  
 +=== Proposed API ===
 <code php> <code php>
 final class Fiber { final class Fiber {
Line 25: Line 28:
   public const STATUS_DEAD      = 4;   public const STATUS_DEAD      = 4;
  
 +  /**
 +   * @param callable $callable any php callable to be paused
 +   * @param int $stack_size fiber stack init size
 +   */
   public function __construct(callable $callable = null, int stack_size = null) {}   public function __construct(callable $callable = null, int stack_size = null) {}
  
 +  /**
 +   * pause the current fiber and ~return~ the $arg1
 +   * as the Fiber::resume's return value.
 +   */
   public static function yield($arg1) {}   public static function yield($arg1) {}
 +  
 +  /**
 +   * Start or resume a fiber.
 +   
 +   * If the fiber is not started, call resume will init
 +   * the $callable with all args.
 +   *
 +   * If the fiber is paused, call resume will send the first arg
 +   * as the last Fiber::yield's return value.
 +   */
   public function resume($arg1...) {}   public function resume($arg1...) {}
 +  
 +  /**
 +   * Throw an exception into the fiber.
 +   
 +   * You code can use try/catch to process error in the
 +   * top level function call. Some framework make heavy
 +   * usage of this feature.
 +   */
   public function throw(Throwable $e) {}   public function throw(Throwable $e) {}
- 
-  /** @throws \UnexpectedValueException */ 
-  public function __wakeup(): void {} 
- 
-  /** @throws \Error */ 
-  private function __clone() {} 
 } }
 </code> </code>
  
 +=== Usage Demo ===
 <code php> <code php>
 function sub1() function sub1()
Line 55: Line 79:
 echo $fiber->resume("hello "); // echo "hello world" echo $fiber->resume("hello "); // echo "hello world"
 </code> </code>
 +
 +=== Implementation Detail ===
 +In our simple implementation, we only backup/restore the **zend stack**. We **cannot** pause a Fiber during internal function call like `array_map`.
 +
 +Backup/restore both the zend stack and the the c statck is impossible. However, it is platform dependent and more  complicated.
 +
 +Martin Schröder is working on this at https://github.com/fiberphp/fiber-ext/pull/30.
 +
 +^Property^Full stack Fiber^Zend stack Fiber^
 +|Code Base|c & asm|c|
 +|Minimum Memory Usage|VM stack only (4 KB)|VM & C stack (4 KB + 4 KB)|
 +|Supported Architecturs|any platform|x86 at this time|
 +|Yield in Internal Function|unsupported|supported|
  
 ===== Backward Incompatible Changes ===== ===== Backward Incompatible Changes =====
Line 80: Line 117:
  
 ===== Open Issues ===== ===== Open Issues =====
-<blockquote>What happens if there are internal calls on the call stack?Say something like array_map(function() { await; }[1, 2, 3]); inside a fiber. Internal calls (using the C stack rather than the VM stackare usually the problem with this kind of endeavor. +<blockquote>Why not introduce helper like **Fiber::alive(),Fiber::running()**?</blockquote>
-</blockquote>+
  
-Fiber does not support yielding during the internal callCalling Fiber::yield in a internal call will cause core dump. +And as a language feature, Fiber should only offer the essential APIUser can implement these methods in user land code easily.
-However, avoiding yield in the internal still make sense and useful+
  
-<blockquote>How do you determine when fiber has returned? Looking at the source, it appears Fiber::status() must be used, comparing against constants. Separate methods similar to Generator would be better.</blockquote>+<blockquote>Why not introduce dedicate method other than **Fiber::resume()** for Fiber initialization?</blockquote>
  
-Offering methods like Fiber::alive, Fiber::running makes no difference to check the Fiber::status() return value. This is just a style issue. And as a language feature, Fiber only offer the essential API and let other works to the user land.+Both Ruby'Fiber and Lua's coroutine using the same **resume()** API to **init** and **resume** their coroutine.
  
-<blockquote>What about throwing exceptions into a fiber?</blockquote>+<blockquote>Why not introduce keyword like async/await?</blockquote>
  
-The Fiber::throw(Exception $exception) has been implemented. +Introducing new keywords will cause BC impact. Both Ruby's Fiber and Lua's coroutine does not have such keyword as well.
- +
-<blockquote>Using Fiber::resume() to initialize the fiber and resume feels awkward. Separate methods again would be better here, perhaps Fiber::init(...$args) and Fiber::resume($send).</blockquote> +
- +
-Both Ruby's Fiber and Lua's coroutine using one **resume** API to init and resume their coroutine. There is no need to offer a dedicate **init** API. +
- +
-<blockquote>What happens if the sub1() function in the RFC is invoked outside of a fiber?</blockquote> +
- +
-You will get a Fatal Error like +
- +
-Fatal error: Uncaught Error: Cannot call Fiber::yield out of Fiber +
- +
-<blockquote>I think a keyword here would be beneficial, even if it has a minor BC impact. Fibers could then be written like generators. `await` or `emit` as a keyword perhaps? This would be a less verbose API, feel less magical (a static method call that actually pauses execution feels out of place), and would allow Fibers to be returned from methods, named functions, etc with less boilerplate.</blockquote> +
- +
-Introducing new keywords like await/emit does not offer any essential benefit but cause BC impact. +
- +
-Both Ruby's Fiber and Lua's coroutine use method to pause and resume their coroutine. There is no need to introduce new keyword.+
  
 ===== Unaffected PHP Functionality ===== ===== Unaffected PHP Functionality =====
Line 117: Line 136:
  
 ===== Proposed Voting Choices ===== ===== Proposed Voting Choices =====
-Simple 50%+1 majority vote.+2/3+1 voting majority
  
 ===== Patches and Tests ===== ===== Patches and Tests =====
-coming soonCurrent developing at https://github.com/fiberphp/fiber-ext +  * https://github.com/php/php-src/pull/3203 
- +  * <del>[[https://github.com/php/php-src/pull/2723]]</del> 
-  * <del>[[https://github.com/php/php-src/pull/2733|GitHub PR #2733]]</del>+  * <del>[[https://github.com/php/php-src/pull/2733]]</del> 
 +  * <del>[[https://github.com/php/php-src/pull/2886]]</del> 
 +  * <del>[[https://github.com/php/php-src/pull/2902]]</del>
  
 ===== Implementation ===== ===== Implementation =====
Line 137: Line 158:
  
 ===== Rejected Features ===== ===== Rejected Features =====
-Keep this updated with features that were discussed on the mail lists. 
rfc/fiber.txt · Last modified: 2018/06/12 07:40 by krakjoe