[1067] in BarnOwl Developers
Rethinking ::Hook
daemon@ATHENA.MIT.EDU (Nelson Elhage)
Thu Oct 29 18:12:41 2009
Resent-From: nelhage@mit.edu
Resent-To: barnowl-dev-mtg@charon.mit.edu
X-Original-To: nelhage@nelhage.com
Date: Sat, 17 May 2008 15:35:59 -0400
From: Nelson Elhage <nelhage@MIT.EDU>
To: barnowl-dev@mit.edu
Hey,
I'd like to think about rethinking how BarnOwl::Hook works.
Currently, for each hook (startup, shutdown, new message, main loop),
we clear all watchers of the hook before a reload, and rely on
reloading the modules to reinstall them.
This has the unfortunate side-effect that we can't reload single
modules, only all-or-nothing. And if a module fails to load because of
e.g. a syntax error, it potentially gets broken, rather than the old
version continuing to run. I think this is on the whole poor.
The reason we have this behavior is to prevent a module's handler from
ending up in the hook list twice. We have to do this because modules
only give us a coderef when registering with a hook, and if the module
has reloaded, the coderef is _different_, so we can't just check if
it's already in the list.
I see at least four different options to allow better behavior. Some
of them can be used together:
1. Have modules register a function name as a string, rather than a
subref. This has the property (not always good) that if the code
changes but the hook doesn't get re-registered, the new hook takes
effect.
2. Use Sub::Identify or similar to ask perl what function the
subroutine represents, and filter the hook list to remove any other
function of that name.
3. Use caller() to figure out which module is registering this hook,
and only de-register hooks for a specific module before reloading
that module
4. Have modules provide a string "name" or identifier for each hook
they register, and remove handlers sharing the same name.
I think, on the whole, that I prefer 2. It does have the property that
anonymous subrefs (i.e. sub{...}) will get registered twice anyways.
Thoughts?
- Nelson