2020-07-11 19:08 GMT, Larry Garfield <la...@garfieldtech.com>:
> On Sat, Jul 11, 2020, at 9:06 AM, Olle Härstedt wrote:
>> Dear internals,
>>
>> I'd like to discuss the concept of ownership in PHP, from the point of
>> view of a new interface UniqueInterface (or SplUniqueInterface or
>> something), which will throw a UniqueException if refcount > 1.
>>
>> Use-case: Mutable objects that cannot be shared (without (deep) cloning).
>>
>> Rational: Immutable objects are considered "easier to reason about"
>> and generally more safe, and as a way to avoid
>> spooky-action-at-a-distance. I argue that mutability is totally fine
>> as long as it's not *being shared*. Currently, there's no way to
>> enforce this in PHP, *but* PHP has a refcounting GC which could do
>> this. This would be a more performant alternative than to build lots
>> of immutable objects using $obj->whereSomething('bla') constructs.
>>
>> Cons: If PHP switches to tracing GC, it will be unusable.
>>
>> What do you think? Should I write it down as an RFC? Implementation
>> should be straight-forward, assuming refcount is manipulated at a
>> single place in the source.
>>
>> Regards
>> Olle
>
> I like the goal of addressing shared mutable state is a laudable one and I
> think most here share it.  However, I think uniqueness checking is the wrong
> approach, for reasons others have already explained.
>
> You're correct that the thing to avoid is shared mutable state.  That can be
> avoided either by getting rid of mutable state or shared state.  Either
> would work.  (Channeling Kevlin Henny here.)
>
> In the case of PHP, since we don't have threads to worry about the main
> source of shared state is reference variables, or refrence-esque objects.
> (Or globals, but I'm assuming most here know to avoid those already.)  That
> is, mutability or shared-ness within a function is, meh, who cares.  It's at
> function boundaries that we care.
>
> As others noted, a ref count check wouldn't help with that much, because the
> act of passing an object to another function necessarily increases the
> refcount, thus eliminating the main benefit.
>
> Rather, the way to eliminate shared-ness is to have "structs," that is,
> objects that pass by value-ish rather than pass-by-reference-ish.  (Yes it's
> more complicated than that, I know, I'm talking about the user-space
> implications.)  PHP 4 objects all worked that way, which was a problem for
> anything with services our resources behind it.  That's why it changed in
> PHP 5 to the more common by-ref-ish behavior, which... is a problem for
> value objects.
>
> Both use cases are valid.  It's why newer languages like Go and Rust take a
> completely different approach to what "object" even means in the first
> place.
>
> It's been discussed before but never really implemented; I do think the way
> to help break the "shared state" side is to allow objects to get flagged as
> "will use by-value passing" or "will use by-reference passing" (again,
> implications, not implementation).  That is, if you have a by-val object and
> pass it to a function, it behaves the same way as passing a string or an
> array: Copy-on-write of the object when any changes are made to properties
> of the object.  Probably we'd also need to require that properties of by-val
> objects cannot be by-ref objects or resources, which seems reasonable to
> me.
>
> I think that would do a far better job of addressing the
> shared-mutable-state issue than reference counting, because it attacks the
> root problem rather than a symptom.
>
> --Larry Garfield
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: https://www.php.net/unsub.php

I think freezing objects might be better fit for my imagined use-case.
The only problem I see is that you can't really unfreeze them. Imagine
a database connection that only can be open/closed at refcount = 1:

```
$connection = new OwnershipConnection();
$connection->open();
$ps = new PostService($connection);
$ps->updateAllPosts();  // Throws exception if $connection->close()
$connection->close();
```

With freeze, you could also do

```
$ps = new PostService($connection->freeze());
```

to ensure it's not closed by mistake. But then you couldn't close the
connection at all, except in __destruct.

Especially, CoW for objects (at opt-in) is not a replacement where
ownership is supposed to replace immutability for performance reason,
e.g. creating a separate immutable database connection for every class
that uses it.

Immutable builder are already part of PSR, e.g. here:
https://www.php-fig.org/psr/psr-7/

I have to wonder how reasonable this is, when freezing or ownership
are also relevant solutions, with different trade-offs.

Olle

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php

Reply via email to