Erik van Velzen wrote on 28/10/2015 15:02:
The ScopeGuard's destructor can now detect the condition:
if ( $this->success_registered ) {
// Function reached checkpoint for this scope
$this->callSuccessHandlers();
} else {
// Function aborted early, due to a throw or early return
$this->callExitHandlers();
}
$this->callExitHandlers();
No boilerplate throw-catch needed, works even if there is already a catch or
finally within the function's definition.
In fact, I kind of want to use this somewhere now... ;)
On the downside, it's worth noting that while PHP destructors are
technically deterministic, the language can actually prevent them
running on scope exit, because Exceptions hold references to everything
used as a parameter in their stack traces.
In the below very simple example, both err() and foo() have completed,
but the destructor fires only once the Exception is caught and
discarded. So if you passed your ScopeGuard object around at all, you
might find things executing in a surprising order.
(Personally, I think this is bad behaviour, and have argued that
Exceptions should not capture these references, but I haven't been able
to convince anyone it's worth changing.)
# https://3v4l.org/Kc9Ck
class KillMe {
public function __destruct() {
echo 'Thank you!';
}
}
function err($ignored) {
throw new Exception;
}
function foo() {
$k = new KillMe;
err($k);
}
try {
foo();
}
catch ( Exception $e ) {
echo 'Handling error. Destructor has not yet fired. ';
}
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php