Hi Niklas, On Tue, Mar 16, 2021 at 8:07 PM Niklas Keller <m...@kelunik.com> wrote: > > Hey Josh, > >> >> > This is a very valid concern to have. However, this code won't simply >> > break if executed asynchronously. >> > It only breaks if the same method (or other methods making use of the same >> > state) is executed concurrently on that object. >> >> I understand this, but of course this will be common in programs where >> fibers are used, and the nature of this proposal means that fibers >> will potentially be highly insidious and quite unpredictable in their >> reach. > > > Concurrent operations on stateful, mutable objects are certainly a risk and > concurrency shouldn't be introduced without thinking about the consequences. > Care must be taken if objects are used across different fibers concurrently, > unless you use global state, then you'll have a harder time adding > concurrency to your application.
I think this is wishful thinking. Real world software uses code from lots of developers and vendors. We can never realistically know the internals of our whole codebase or read through every line of code in order to evaluate whether we think each library we are using has been designed with fiber support in mind. A solution which relies on this is wishful thinking. >> >> > If you can see the race condition here, you can probably also see the race >> > condition in the original snippet above. >> >> The difference is that in the second case, the developer has >> *explicitly opted into the underlying call being async*. I.e. they >> expect it, and can design with it in mind. > > > While the developer opted into async / non-blocking I/O, they still might not > have thought about concurrent operations on that same object. But at least you know that the developer *intends* for the code to be run with fibers. This is especially important for third party code. >> > Being able to use the type system is a concern the RFC solves, but that's >> > rather just nice-to-have. The relevant problem is the call stack pollution >> > or "What color is your function" problem. It simply doesn't make sense for >> > applications and libraries to offer an async and non-async interface for >> > everything. Due to the "What color is your function" problem, there can't >> > be a gradual migration to non-blocking I/O, which will mostly result in >> > non-blocking I/O simply not being supported by the majority of libraries, >> > making it basically non-viable in PHP. >> >> 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. For example >> >> private function capturePayment(): void >> { >> $paymentRequest = preparePaymentRequest($this->currentOrder); >> // allow, but don't require, the underlying call to use >> fibers. Callers higher up the stack would also have to opt in >> async $this->paymentGateway->capturePayment($paymentRequest); >> >> $this->currentOrder->setTransactionId($paymentRequest->getTransactionId()); >> } >> >> With this approach, APIs we'd avoid the "what colour is your function" >> problem without sacrificing the safety that we really need in e.g. >> ecommerce. > > > This doesn't really avoid the "what color is your function" problem, as you'd > have to mark all function calls with "async" then, eventually resulting in > every PHP function call having to be prefixed with "async". I certainly don't think we should expect to be in a position where all functions are async. Business logic is (should generally be) in pure, side effect free functions which, by definition, are not doing any IO. The point is to avoid accidentally making that code async. To clarify, my suggestion is that a keyword at the callsite would allow the callsite to opt in to fibers in the called function if that function supports fibers, and if we are currently within a fiber context, otherwise it would behave synchronously. > Rather than marking methods with "synchronized" as mentioned before, it might > be more feasible to mark methods with a keyword if they allow concurrent > operations. I'll have to research which options are viable. > > Best, > Niklas I do appreciate your time, and I'm sorry for not asking these questions during the discussion period. I'll leave it here unless others feel the discussion is worth continuing. Thanks -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php