Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:113637 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 46377 invoked from network); 20 Mar 2021 02:18:49 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 20 Mar 2021 02:18:49 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id BB87F1804C0 for ; Fri, 19 Mar 2021 19:13:27 -0700 (PDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE autolearn=no autolearn_force=no version=3.4.2 X-Spam-Virus: No X-Envelope-From: Received: from mail-qk1-f195.google.com (mail-qk1-f195.google.com [209.85.222.195]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Fri, 19 Mar 2021 19:13:27 -0700 (PDT) Received: by mail-qk1-f195.google.com with SMTP id z10so4957329qkz.13 for ; Fri, 19 Mar 2021 19:13:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=newclarity-net.20150623.gappssmtp.com; s=20150623; h=mime-version:subject:from:in-reply-to:date:cc :content-transfer-encoding:message-id:references:to; bh=1CWrQljoq8DS45oq+lQAtWIIWO6yaKaQnt2NdieBiuY=; b=RCJHymPd6UKWuGm8kGxgbWB/5oRh3h+zPllXrhNFeUFg5ZhXGUdP/Ej0YLFPOHaXoX F18NOFxgSS8UnDKV5TqbwF1dxPiyCwvt3KZRsX2tB0Pvo78T8oaDsWHPid6nYy1ev/xl tl3nuumiZ6MlAC0D0E5a4VfROEdTgH041D7KFDcrbO6ThTjdckA6ZfLfJFeeFAPvQPUE b7YHz7HmfJvhrCTDLDYooP1aLlf2wJ0GND1G/4fEC5ZSYUM8EOAI7n45+tQe3WDk6tDG FMD0e5Eb8XYuMWCMgo+u+B2De1wklidX7bNCl/e7e/A35UOgFz1XWJjdaK27PqxZzvXy peNQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:subject:from:in-reply-to:date:cc :content-transfer-encoding:message-id:references:to; bh=1CWrQljoq8DS45oq+lQAtWIIWO6yaKaQnt2NdieBiuY=; b=c/6So/RoTKkiR/1pmU1TKzaXzK7mbnVL71QoXBfqXsTpNTk0kQekI/aL12+D049qzy s1rtj8AVlLAko5Xnm2fNUi/BNHVx8e1FfVbHcwJAOYQytiT3AkwBHQ23OqhNOIlFuu+r BieFe7/h+Vqjz9wJVRiAYrXm95t2P4LQALwy7bwDgGn2fImD5zrUW0IWB2hPwp0LEOsq KbuDa03yGz/+MQynnius/iDLpb/u3JedXbs1ZwnVPrJQ34Y3HI4DS6Q/GVRxZ7Bpdu9h jDPz9aZ1nbetR0iyRtWkZtzmNIyTqUdu1fs6WI93BbugunDzKMGIwbrWuV4SdNDv+PIo CtbQ== X-Gm-Message-State: AOAM532JxGhGYX4WAj8tU046rhv8QrkJfvpHOp94pi918fbWWpNJGZCm jKoLOS5+RTEiYfOU82eN6yOlvw== X-Google-Smtp-Source: ABdhPJzp2ouEAYkKGuKSjjOvAekdqYH5sCAaLuQOD8JP/KzB9l9/5Uc/Nt8s7h3zlh7BPzPex0x7ow== X-Received: by 2002:a37:ef15:: with SMTP id j21mr1418052qkk.385.1616206405666; Fri, 19 Mar 2021 19:13:25 -0700 (PDT) Received: from [192.168.1.239] (c-24-98-254-8.hsd1.ga.comcast.net. [24.98.254.8]) by smtp.gmail.com with ESMTPSA id 73sm5832463qkk.131.2021.03.19.19.13.24 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 19 Mar 2021 19:13:25 -0700 (PDT) Content-Type: text/plain; charset=us-ascii Mime-Version: 1.0 (Mac OS X Mail 13.4 \(3608.120.23.2.4\)) In-Reply-To: Date: Fri, 19 Mar 2021 22:13:24 -0400 Cc: internals@lists.php.net Content-Transfer-Encoding: quoted-printable Message-ID: References: <70951423-5e77-c150-6dce-dd3c62f8dc8b@php.net> <0b994a60-7970-605b-1657-d6ee732690e5@gmx.de> <5C73A1DE-E563-4F69-B8C7-6506F81D7345@trowski.com> To: Rowan Tommins X-Mailer: Apple Mail (2.3608.120.23.2.4) Subject: Re: [PHP-DEV] [VOTE] Fibers From: mike@newclarity.net (Mike Schinkel) > On Mar 19, 2021, at 3:55 PM, Rowan Tommins = wrote: >=20 > On 18/03/2021 09:20, Josh Di Fabio wrote: >> "If you want to enable fibers in your application, you must be >> confident about the implementation details of all of the code in your >> application, including that of your dependencies, which are written >> and maintained by other developers." >>=20 >> I don't have anything to add to my previous point in that I disagree >> that this is practical. >=20 >=20 > While I agree that this is extremely difficult, and slows adoption of = asynchronous technologies, I think the challenge is not identifying = asynchronous code, it's identifying shared state. >=20 > In your example, you show code that was written to use shared state = unwittingly calling code that was written to be asynchronous: >=20 > private function capturePayment() > { > $paymentRequest =3D = preparePaymentRequest($this->currentOrder); > $this->paymentGateway->capturePayment($paymentRequest); > = $this->currentOrder->setTransactionId($paymentRequest->getTransactionId())= ; > } >=20 > However, the same problem exists the other way around - code written = to be asynchronous unwittingly calling code written to use shared state: >=20 > private async function capturePayment() > { > $paymentRequest =3D = $this->someDependency->preparePaymentRequest(); > await $this->paymentGateway->capturePayment($paymentRequest); > = $this->someDependency->setTransactionId($paymentRequest->getTransactionId(= )); > } >=20 > This all looks fine - but what if someDependency is actually calling = into a library which stores the current order in a static variable? Now = you have exactly the same race condition for the opposite reason. And = the solution is the same: carefully vet all your dependencies. >=20 >=20 > I can think of a few ways of solving this: >=20 > 1) Require all the code to be synchronous. This is easy in PHP, even = if Fibers are supported: just don't run in an asynchronous framework. >=20 > 2) Require most of the code to be synchronous. This is the common = approach of labelling functions as "async" or converting return values = to Generators or Promises. The big disadvantage is that it requires = rewriting a lot of code that doesn't care one way or the other if it's = called synchronously. >=20 > 3) Require all the code to be free of shared state. This is ultimately = the only way you'll get the full advantage of asynchronous code. GoLang uses goroutines for this. Goroutines allow code written by responsible developers for use by = others to ensure their packages are safe for consumption by others. The = Go mantra related to concurrency is "Do not communicate by sharing = memory; instead, share memory by communicating." https://blog.golang.org/codelab-share Having experience with Go, channels work brilliantly for allowing = concurrent routines access to the same data, albeit in a controlled = manner. > 4) Require most of the code to be free of shared state. Having some = primitives in the language to mark out code that definitely *can't* be = asynchronous would probably be useful. Perhaps you could mark a function = as "no-interrupt"; this could then be used as a wrapper when calling = into a library you know or suspect of using state in unsafe ways. >=20 >=20 >> Perhaps we could rather make fibers*opt in* at the*callsite* >> (similar to goroutine calls) in order to prevent functions >> unexpectedly being executed asynchronously due to faraway changes. >> This would be safe and predictable while also avoiding the "What = color >> is your function" problem. >=20 >=20 > Although this would avoid keeping both synchronous and asynchronous = versions of the same function, it would require adding that keyword to = every single function call, just in case somewhere inside it wants to = take advantage of your asynchronous environment. >=20 > =46rom my limited understanding, goroutines are a completely different = concept. Saying "go someFunction()" in Go immediately starts a new = thread-like thing, and doesn't return anything. The runtime manages the = scheduling of the thread, but if you want to get any data out of the = goroutine, you have to pass it explicitly, e.g. via a channel. Just in case it is relevant for anyone reading this discussion who is = not familiar with Go this short article compares and contrasts = goroutines vs. threads: https://www.geeksforgeeks.org/golang-goroutine-vs-thread/ #fwiw -Mike=