On 30/06/2022 10:20, Robert Landers wrote:
I think their suggested code would work (at least currently in PHP) by
the simple fact they would increase the reference count on that
object/resource until they set it as null. However, with the
"optimization," the reference count will never be incremented and thus
fail to work as defined.
No, the captured value is tied to the lifetime of the closure itself,
not the variable inside the closure.
$some_resource = acquire_some_resource();
// refcount=1 (outer $some_resource)
$fn = function() use ($some_resource) {
$some_resource = null;
}
// refcount=2 (outer $some_resource, closure $fn)
$fn();
// during execution, refcount is 3 (outer $some_resource, closure $fn,
local $some_resource)
// once the local variable is written to, the refcount goes back to 2
(outer $some_resource, closure $fn)
unset($some_resource);
// refcount=1 (closure $fn)
$fn();
// the captured variable always starts with its original value,
regardless of how many times you execute the function
// during execution, refcount is now 2 (closure $fn, local $some_resource)
// after execution, refcount is still 1 (closure $fn)
unset($fn);
// only now does the refcount go down to 0 and trigger the destructor
The only way for it to work would be using capture by reference (not
supported by the proposed short syntax):
$some_resource = acquire_some_resource();
// refcount=1: simple variable
$fn = function() use (&$some_resource) {
$some_resource = null;
}
// refcount=1: a reference set with 2 members (outer $some_resource,
closure $fn)
$fn();
// during execution, we have a reference set with 3 members (outer
$some_resource, closure $fn, local $some_resource)
// the assignment assigns to this reference set, changing the value
referenced by all 3 members
// refcount on the resource drops from 1 to 0, triggering the destructor
$fn();
// because it was captured by reference, the initial value of
$some_resource in the closure has now changed
Regards,
--
Rowan Tommins
[IMSoP]
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php