1 # This file was automatically generated by SWIG (http://www.swig.org).
4 # Don't modify this file, modify the SWIG interface instead.
6 package Amanda::MainLoop;
9 @ISA = qw(Exporter DynaLoader);
10 package Amanda::MainLoopc;
11 bootstrap Amanda::MainLoop;
12 package Amanda::MainLoop;
15 # ---------- BASE METHODS -------------
17 package Amanda::MainLoop;
20 my ($classname,$obj) = @_;
21 return bless $obj, $classname;
31 my ($self,$field) = @_;
32 my $member_func = "swig_${field}_get";
33 $self->$member_func();
37 my ($self,$field,$newval) = @_;
38 my $member_func = "swig_${field}_set";
39 $self->$member_func($newval);
48 # ------- FUNCTION WRAPPERS --------
50 package Amanda::MainLoop;
52 *run_c = *Amanda::MainLoopc::run_c;
53 *quit = *Amanda::MainLoopc::quit;
54 *timeout_source = *Amanda::MainLoopc::timeout_source;
55 *idle_source = *Amanda::MainLoopc::idle_source;
56 *child_watch_source = *Amanda::MainLoopc::child_watch_source;
57 *fd_source = *Amanda::MainLoopc::fd_source;
59 ############# Class : Amanda::MainLoop::Source ##############
61 package Amanda::MainLoop::Source;
62 use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
63 @ISA = qw( Amanda::MainLoop );
68 my $self = Amanda::MainLoopc::new_Source(@_);
69 bless $self, $pkg if defined($self);
73 return unless $_[0]->isa('HASH');
74 my $self = tied(%{$_[0]});
75 return unless defined $self;
76 delete $ITERATORS{$self};
77 if (exists $OWNER{$self}) {
78 Amanda::MainLoopc::delete_Source($self);
83 *set_callback = *Amanda::MainLoopc::Source_set_callback;
84 *remove = *Amanda::MainLoopc::Source_remove;
87 my $ptr = tied(%$self);
93 my $ptr = tied(%$self);
98 # ------- VARIABLE STUBS --------
100 package Amanda::MainLoop;
102 *G_IO_IN = *Amanda::MainLoopc::G_IO_IN;
103 *G_IO_OUT = *Amanda::MainLoopc::G_IO_OUT;
104 *G_IO_PRI = *Amanda::MainLoopc::G_IO_PRI;
105 *G_IO_ERR = *Amanda::MainLoopc::G_IO_ERR;
106 *G_IO_HUP = *Amanda::MainLoopc::G_IO_HUP;
107 *G_IO_NVAL = *Amanda::MainLoopc::G_IO_NVAL;
114 Amanda::MainLoop - Perl interface to the Glib MainLoop
118 use Amanda::MainLoop;
120 my $to = Amanda::MainLoop::timeout_source(2000);
121 $to->set_callback(sub {
122 print "Time's Up!\n";
123 $to->remove(); # dont' re-queue this timeout
124 Amanda::MainLoop::quit(); # return from Amanda::MainLoop::run
127 Amanda::MainLoop::run();
129 Note that all functions in this module are individually available for export,
132 use Amanda::MainLoop qw(run quit);
136 The main event loop of an application is a tight loop which waits for events,
137 and calls functions to respond to those events. This design allows an IO-bound
138 application to multitask within a single thread, by responding to IO events as
139 they occur instead of blocking on particular IO operations.
141 The Amanda security API, transfer API, and other components rely on the event
142 loop to allow them to respond to their own events in a timely fashion.
144 The overall structure of an application, then, is to initialize its state,
145 register callbacks for some events, and begin looping. When some
146 application-defined state is reached, the loop is terminated and the
147 application cleans up and exits.
151 The actual event loop takes place within a call to C<Amanda::MainLoop::run()>.
152 This function executes until a call to C<Amanda::MainLoop::quit()> occurs, at
153 which point C<run()> returns. You can check whether the loop is running with
154 C<Amanda::MainLoop::is_running()>.
156 In some cases, a sub should only run after the loop has started. The
157 most common case is when a callback may call C<Amanda::MainLoop::quit>
158 immediately. In this circumstance, use C<call_later>, which takes a
159 subref and an arbitrary number of arguments for that sub:
162 my ($letters, $digits) = @_;
164 Amanda::MainLoop::quit();
166 Amanda::MainLoop::call_later($cb, "abc", 123);
168 Amanda::MainLoop::run();
170 Similarly, a tight loop of callbacks with no blocking operations can
171 lead to excessive stack consumption. In this case, C<call_later()> is
172 useful, too. It queues the callback to run at the next cycle of the
177 if (can_do_it_now()) {
178 my $result = do_it();
179 Amanda::MainLoop::call_later($cb, $result)
187 An event source is responsible for producing events. A source may produce
188 multiple events over its lifetime.
190 The method C<$src->set_callback(\&cb)> sets the function that will be called
191 for a given source, and "attaches" the source to the main loop so that it will
192 begin generating events. The arguments to the callback depend on the event
193 source, but the first argument is always the source itself. Unless specified,
194 no other arguments are provided.
196 Event sources persist until they are removed with C<$src->remove()>, even if
197 the source itself is no longer accessible from Perl. Although Glib supports
198 it, there is no provision for "automatically" removing an event source. As an
204 Amanda::MainLoop::timeout_source(200)->set_callback(sub {
209 Amanda::MainLoop::quit();
214 Amanda::MainLoop::run();
218 my $src = Amanda::MainLoop::timeout_source(10000);
220 A timeout source will create events at the specified interval, specified in
221 milliseconds (thousandths of a second). The events will continue until the
226 my $src = Amanda::MainLoop::idle_source(2);
228 An idle source will create events continuously except when a higher-priority
229 source is emitting events. Priorities are generally small positive integers,
230 with larger integers denoting lower priorities. The events will continue until
231 the source is destroyed.
235 my $src = Amanda::MainLoop::child_watch_source($pid);
237 A child watch source will issue an event when the process with the given PID
238 dies. To avoid race conditions, it will issue an event even if the process
239 dies before the source is created. The callback is called with three
240 arguments: the event source, the PID, and the child's exit status.
242 Note that this source is totally incompatible with any thing that would cause
243 perl to change the SIGCHLD handler. If SIGCHLD is changed, under some
244 circumstances the module will recognize this circumstance, add a warning to the
245 debug log, and continue operating. However, it is impossible to catch all
248 =head3 File Descriptor
250 my $src = Amanda::MainLoop::fd_source($fd, G_IO_IN);
252 This source will issuen an event whenever one of the given conditions is true
253 for the given file descriptor. The conditions are from Glib's GIOCondition,
254 and are C<$G_IO_IN>, C<G_IO_OUT>, C<$G_IO_PRI>, C<$G_IO_ERR>, C<$G_IO_HUP>, and
255 C<$G_IO_NVAL>. These constants are available with the import tag
258 Generally, when reading from a file descriptor, use C<$G_IO_IN|$G_IO_HUP> to
259 ensure that an EOF triggers an event as well. Writing to a file descriptor can
260 simply use C<$G_IO_OUT>.
262 =head1 RELATION TO GLIB
264 Glib's main event loop is described in the Glib manual:
265 L<http://library.gnome.org/devel/glib/stable/glib-The-Main-Event-Loop.html>.
266 Note that Amanda depends only on the functionality available in Glib-2.2.0, so
267 many functions described in that document are not available in Amanda. This
268 module provides a much-simplified interface to the glib library, and is not
269 intended as a generic wrapper for it. Specifically:
273 =item Amanda's perl-accessible main loop only runs a single C<GMainContext>, and
274 always runs in the main thread.
276 =item Besides idle sources, event priorities are not accessible from Perl.
280 =head1 PROGRAMMING HINTS
282 Most often, callbacks are short, and can be specified as anonymous subs:
284 $src->set_callback(sub {
289 There is currently no means in place to specify extra arguments for a callback
290 when it is set. If the callback needs access to other data, it should use a
291 Perl closure in the form of lexically scoped variables and a (possibly
295 my $total_results = 0;
297 $src->set_callback(sub {
298 my ($src, $result) = @_;
299 $total_results += $result;
303 Event sources are often set up in groups, e.g., a long-term operation and a
304 timeout. When this is the case, be careful that all sources are removed when
305 the operation is complete. The easiest way to accomplish this is to include all
306 sources in a lexical scope and remove them at the appropriate times:
309 my $op_src = long_operation_src();
310 my $timeout_src = Amanda::MainLoop::timeout_source($timeout);
314 $timeout_src->remove();
317 $op_src->set_callback(sub {
318 print "Operation complete\n";
322 $timeout_src->set_callback(sub {
323 print "Operation timed out\n";
328 Both of these limitations may be lifted in future revisions of
333 # glib's g_is_main_loop_running() seems inaccurate, so we just
334 # track that information locally..
335 my $mainloop_running = 0;
337 my @waiting_to_call_later;
339 my ($sub, @args) = @_;
341 # add the callback if nothing is waiting right now
342 if (!@waiting_to_call_later) {
343 timeout_source(0)->set_callback(sub {
347 while (@waiting_to_call_later) {
348 my ($sub, @args) = @{pop @waiting_to_call_later};
354 push @waiting_to_call_later, [ $sub, @args ];
358 $mainloop_running = 1;
360 $mainloop_running = 0;
364 return $mainloop_running;
367 push @EXPORT_OK, qw(GIOCondition_to_strings);
368 push @{$EXPORT_TAGS{"GIOCondition"}}, qw(GIOCondition_to_strings);
370 my %_GIOCondition_VALUES;
371 #Convert a flag value to a list of names for flags that are set.
372 sub GIOCondition_to_strings {
376 for my $k (keys %_GIOCondition_VALUES) {
377 my $v = $_GIOCondition_VALUES{$k};
379 #is this a matching flag?
380 if (($v == 0 && $flags == 0) || ($v != 0 && ($flags & $v) == $v)) {
385 #by default, just return the number as a 1-element list
393 push @EXPORT_OK, qw($G_IO_IN);
394 push @{$EXPORT_TAGS{"GIOCondition"}}, qw($G_IO_IN);
396 $_GIOCondition_VALUES{"G_IO_IN"} = $G_IO_IN;
398 push @EXPORT_OK, qw($G_IO_OUT);
399 push @{$EXPORT_TAGS{"GIOCondition"}}, qw($G_IO_OUT);
401 $_GIOCondition_VALUES{"G_IO_OUT"} = $G_IO_OUT;
403 push @EXPORT_OK, qw($G_IO_PRI);
404 push @{$EXPORT_TAGS{"GIOCondition"}}, qw($G_IO_PRI);
406 $_GIOCondition_VALUES{"G_IO_PRI"} = $G_IO_PRI;
408 push @EXPORT_OK, qw($G_IO_ERR);
409 push @{$EXPORT_TAGS{"GIOCondition"}}, qw($G_IO_ERR);
411 $_GIOCondition_VALUES{"G_IO_ERR"} = $G_IO_ERR;
413 push @EXPORT_OK, qw($G_IO_HUP);
414 push @{$EXPORT_TAGS{"GIOCondition"}}, qw($G_IO_HUP);
416 $_GIOCondition_VALUES{"G_IO_HUP"} = $G_IO_HUP;
418 push @EXPORT_OK, qw($G_IO_NVAL);
419 push @{$EXPORT_TAGS{"GIOCondition"}}, qw($G_IO_NVAL);
421 $_GIOCondition_VALUES{"G_IO_NVAL"} = $G_IO_NVAL;
423 #copy symbols in GIOCondition to constants
424 push @{$EXPORT_TAGS{"constants"}}, @{$EXPORT_TAGS{"GIOCondition"}};