Re: Possible RFC: UniqueInterface that throws except ion at refcount > 1
| From: | Larry Garfield | Date: | Sat, 11 Jul 2020 19:08:54 +0000 |
| Subject: | Re: Possible RFC: UniqueInterface that throws except ion at refcount > 1 | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-110953@lists.php.net to get a copy of this message | ||
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