NAME
App::Chart::Glib::Ex::SignalBlock -- block signal handlers with scope guard style
SYNOPSIS
use App::Chart::Glib::Ex::SignalBlock;
{
my $blocker = App::Chart::Glib::Ex::SignalBlock->new ($obj, $id);
# handler $id for activate is not called
$obj->activate;
}
# until $blocker goes out of scope ...
DESCRIPTION
Not sure about the arguments yet ...
Blocking may be more work than disconnecting and re-connecting ...
App::Chart::Glib::Ex::SignalBlock
temporarily blocks a particular signal handler connection using signal_handler_block
. When the blocker object is destroyed it unblocks with signal_handler_unblock
.
The idea is that it can be easier to manage the lifespan of an object than to ensure every exit point from a particular bit of code includes an unblock. For example a temporary blocking in a Perl scope, knowing no matter how it exits (error, goto, return, etc) the signal block will be undone.
{
my $blocker = App::Chart::Glib::Ex::SignalBlock->new ($obj,$id);
...
}
Or objects can help to manage longer lived blocking, so as not to lose track of things held for a period of time or main loop conditions etc.
It works to nest blockers, done either with SignalBlock or explicit calls. Glib simply keeps a count of current blocks on each connected ID, which means there's no need for proper nesting, blockers can overlap in any fashion.
Alternatives
You can also simply arrange for your signal handler to do nothing when it sees a global variable or a flag in an object.
our $update_in_progress;
sub my_handler {
return if $update_in_progress;
...
}
{
local $update_in_progress = 1;
...
}
If my_handler
is called many times during the "update" the repeated do-nothing calls could be slow and a block (or disconnect) the signal may be better. On the other hand if there's just a few calls then the overhead of creating a blocker object might be the slowest part.
FUNCTIONS
$blocker = App::Chart::Glib::Ex::SignalBlock->new ($object,$id,...)
-
Do a
$object->signal_handler_block
on each given$object
and signal handler$id
, and return a SignalBlock object which will make corresponding$object->signal_handler_unblock
calls when it's destroyed. So for instance if you were thinking of$obj->signal_handler_block ($id); ... $obj->signal_handler_unblock ($id);
instead use
{ my $blocker = App::Chart::Glib::Ex::SignalBlock->new ($obj,$id); ... # automatic signal_handler_unblock when $blocker out of scope }
SignalBlock holds weak references to the target objects, so the mere fact a signal is blocked won't an object alive once nothing else cares if it lives or dies.
OTHER NOTES
When there's multiple signals in a SignalBlock it's currently unspecified what order the unblock calls are made. (What would be good? First-in first-out, or a stack?) You can create multiple SignalBlock objects and arrange your blocks to destroyed them in a particular order if it matters.
There's quite a few general purpose block-scope cleanup systems if you want more than signal blocking. Scope::Guard, AtExit, Sub::ScopeFinalizer and Guard use the destructor style. Hook::Scope and B::Hooks::EndOfScope manipulate the code in a block.
SEE ALSO
Glib::Object, Glib::Ex::FreezeNotify
HOME PAGE
http://user42.tuxfamily.org/glib-ex-objectbits/index.html
LICENSE
Copyright 2008, 2009, 2010, 2011 Kevin Ryde
Glib-Ex-ObjectBits is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version.
Glib-Ex-ObjectBits is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Glib-Ex-ObjectBits. If not, see http://www.gnu.org/licenses/.