Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:100344 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 20419 invoked from network); 1 Sep 2017 14:25:36 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 1 Sep 2017 14:25:36 -0000 Authentication-Results: pb1.pair.com header.from=me@kelunik.com; sender-id=unknown Authentication-Results: pb1.pair.com smtp.mail=me@kelunik.com; spf=permerror; sender-id=unknown Received-SPF: error (pb1.pair.com: domain kelunik.com from 81.169.146.163 cause and error) X-PHP-List-Original-Sender: me@kelunik.com X-Host-Fingerprint: 81.169.146.163 mo4-p00-ob.smtp.rzone.de Received: from [81.169.146.163] ([81.169.146.163:20594] helo=mo4-p00-ob.smtp.rzone.de) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 0F/AA-04538-DDD69A95 for ; Fri, 01 Sep 2017 10:25:34 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; t=1504275930; s=domk; d=kelunik.com; h=Content-Type:Cc:To:Subject:Date:From:References:In-Reply-To: MIME-Version; bh=GwGYHgGbkWwM9P6oPb6G/R7qnahrmWP+MgVKuGKw9lY=; b=BzMsRR4xaaJ5UcStdFhZ95HKmvTKY5Hc8xqBLDgX+fOm561dv0qdCOWngnXx/7Mqin HodWIAj+4KcNGgpN+S/xBlLAUQw5M1TQgFfFm85T1YAUQR/UTpIHl0ZMw8fJAa//5RLt UFiiiP/VlEGi8B7o8sJsUlrYoe3xoxyEkobe8= X-RZG-AUTH: :IWkkfkWkbvHsXQGmRYmUo9mls2vWuiu+7SLDup6E67mzuYROBqD+uXg= X-RZG-CLASS-ID: mo00 Received: by mail-yw0-f169.google.com with SMTP id t188so1846375ywb.1 for ; Fri, 01 Sep 2017 07:25:30 -0700 (PDT) X-Gm-Message-State: AHPjjUjtEO4LaSjEvp4LEKziqRQbQnMW37QnSHCAjfFInPEKFF3BUWK9 UgrY8zejjE7nYe3GYbnJKEoP80UFGg== X-Google-Smtp-Source: ADKCNb5/Xdz6x2r42KJT2NIMJB6g4eS7aWhd6ei+bmy1DcufDDi+ZYrX5zsJxABv1QMTS6OYr++A5No7ycTAHeiQAlU= X-Received: by 10.37.87.4 with SMTP id l4mr1841131ybb.263.1504275929885; Fri, 01 Sep 2017 07:25:29 -0700 (PDT) MIME-Version: 1.0 Received: by 10.37.176.131 with HTTP; Fri, 1 Sep 2017 07:25:29 -0700 (PDT) In-Reply-To: <8DB5D7F2-CB7A-4324-AB9F-D9934DD9C108@lvht.net> References: <7E991FBB-C115-4AB9-B904-EBE7C0F24089@lvht.net> <8DB5D7F2-CB7A-4324-AB9F-D9934DD9C108@lvht.net> Date: Fri, 1 Sep 2017 16:25:29 +0200 X-Gmail-Original-Message-ID: Message-ID: To: Haitao Lv Cc: Rowan Collins , PHP Internals Content-Type: multipart/alternative; boundary="001a113e817071f3350558218815" Subject: Re: [PHP-DEV] add Fiber (sackful coroutine) support From: me@kelunik.com (Niklas Keller) --001a113e817071f3350558218815 Content-Type: text/plain; charset="UTF-8" 2017-09-01 15:02 GMT+02:00 Haitao Lv : > > > On 1 Sep 2017, at 20:45, Rowan Collins wrote: > > > > Is this your own invention, or is the name and semantics based on some > existing language or computer science theory? "Fiber" makes me think of > strings, rather than coroutines, so maybe I'm missing a key metaphor here. > > Fiber is a lightweight thread. Please see > https://en.wikipedia.orghttps://github.com/amphp/artax/blob/master/lib/HttpTunneler.php/wiki/ > Fiber_(computer_science) > > And ruby support Fiber. Please see https://ruby-doc.org/core-2.4. > 1/Fiber.html > > > > >>> >>> function foo($a) > >>> { > >>> $b = await $a + 1; > >>> echo $b; > >>> } > > > > Should "await" be "yield" here? If not, what happens if I call foo() > without being inside a Fiber? > > No. A function with a yield will always return a Generator object. A fiber > with await will return any > value. You can see the await as a resumable return. The value after it > will be returned and the function > will be paused. > > > > > Similarly, if I run bar() and it runs foo(), what result will I get > outside a Fiber, since bar() has no yield, so is not itself a generator? > > > > > >> So the Fiber API is a little like the Generator API, but is more simple > >> yet powerful. So there > >> is no need to distinct $generator->current(), $generator->send(), and > >> $generator->getReturn(). > > > > Your ->resume() doesn't seem to do anything a normal generator can't, > except that the yield is nested deeper. > > The await is a nested deeper yield! > > > Nor does it seem to replace getReturn(). > > $f = new Fiber(function ($a) { > return 1; > }); > > echo $f->resume(); // will output 1 > > > Meanwhile, how does this relate to other ways of combining generators, > such as "yield from"? > > You can use Fiber to implement a more simple generator, because fiber can > be paused/resumed in its deeper > call. > > function bar() > { > foreach ([5,6] as $i) { > await $i; > } > } > function foo() > { > foreach ([3,4] as $i) { > await $i; > } > bar(); > } > $f = new Fiber(function ($a) { > await 1; > foo(); > }); > > echo $f->resume(); // will output 1 > echo $f->resume(); // will output 2 > echo $f->resume(); // will output 3 > echo $f->resume(); // will output 4 > echo $f->resume(); // will output 5 > echo $f->resume(); // will output 6 Fibres / Green Threads solve the problem that coroutine- / promise-based APIs need to be viral. If any subroutine needs to await something without blocking everything else, every parent also needs to return a promise and be aware of it. However, I'm not entirely sure whether they're the better solution. Currently every `yield` in a coroutine in Amp is an interruption point. Between two `yield`s, everything is synchronous. If every function call can now potentially await things, other things might happen (unexpectedly) concurrently. This would need special care for some things. The current main pain point I see for libraries like Amp is not the problem of viral promise-APIs. It's rather the need for the boilerplate of `Amp\call(function () use ($arg1, $arg2, ...) { ... }` for every coroutine to return a promise instead of a generator, because generators are an implementation detail, see e.g. https://github.com/amphp/artax/blob/63f044eea7a67ac5f703232f6710846125a73fe3/lib/HttpTunneler.php#L21 A potential way around that (might be a stupid idea I just had): Allow defining "wrappers" per file, that auto-wrap marked functions. ```php