990fb90c5c7a610d7ac85c1828d98ab781e7bc5e
[debian/amanda] / perl / Amanda / MainLoop.pm
1 # This file was automatically generated by SWIG (http://www.swig.org).
2 # Version 1.3.39
3 #
4 # Do not make changes to this file unless you know what you are doing--modify
5 # the SWIG interface file instead.
6
7 package Amanda::MainLoop;
8 use base qw(Exporter);
9 use base qw(DynaLoader);
10 package Amanda::MainLoopc;
11 bootstrap Amanda::MainLoop;
12 package Amanda::MainLoop;
13 @EXPORT = qw();
14
15 # ---------- BASE METHODS -------------
16
17 package Amanda::MainLoop;
18
19 sub TIEHASH {
20     my ($classname,$obj) = @_;
21     return bless $obj, $classname;
22 }
23
24 sub CLEAR { }
25
26 sub FIRSTKEY { }
27
28 sub NEXTKEY { }
29
30 sub FETCH {
31     my ($self,$field) = @_;
32     my $member_func = "swig_${field}_get";
33     $self->$member_func();
34 }
35
36 sub STORE {
37     my ($self,$field,$newval) = @_;
38     my $member_func = "swig_${field}_set";
39     $self->$member_func($newval);
40 }
41
42 sub this {
43     my $ptr = shift;
44     return tied(%$ptr);
45 }
46
47
48 # ------- FUNCTION WRAPPERS --------
49
50 package Amanda::MainLoop;
51
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;
58
59 ############# Class : Amanda::MainLoop::Source ##############
60
61 package Amanda::MainLoop::Source;
62 use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
63 @ISA = qw( Amanda::MainLoop );
64 %OWNER = ();
65 %ITERATORS = ();
66 sub new {
67     my $pkg = shift;
68     my $self = Amanda::MainLoopc::new_Source(@_);
69     bless $self, $pkg if defined($self);
70 }
71
72 sub DESTROY {
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);
79         delete $OWNER{$self};
80     }
81 }
82
83 *set_callback = *Amanda::MainLoopc::Source_set_callback;
84 *remove = *Amanda::MainLoopc::Source_remove;
85 sub DISOWN {
86     my $self = shift;
87     my $ptr = tied(%$self);
88     delete $OWNER{$ptr};
89 }
90
91 sub ACQUIRE {
92     my $self = shift;
93     my $ptr = tied(%$self);
94     $OWNER{$ptr} = 1;
95 }
96
97
98 # ------- VARIABLE STUBS --------
99
100 package Amanda::MainLoop;
101
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;
108
109 @EXPORT_OK = ();
110 %EXPORT_TAGS = ();
111
112 =head1 NAME
113
114 Amanda::MainLoop - Perl interface to the Glib MainLoop
115
116 =head1 SYNOPSIS
117
118     use Amanda::MainLoop;
119     
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
125     });
126
127     Amanda::MainLoop::run();
128
129 Note that all functions in this module are individually available for export,
130 e.g.,
131
132     use Amanda::MainLoop qw(run quit);
133
134 =head1 OVERVIEW
135
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.
140
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.
143
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.
148
149 =head2 LOOPING
150
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()>.
155
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:
160
161     my $cb = sub {
162         my ($letters, $digits) = @_;
163         # ..
164         Amanda::MainLoop::quit();
165     };
166     Amanda::MainLoop::call_later($cb, "abc", 123);
167     # ..
168     Amanda::MainLoop::run();
169
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
173 MainLoop:
174
175     sub might_delay {
176         my ($cb) = @_;
177         if (can_do_it_now()) {
178             my $result = do_it();
179             Amanda::MainLoop::call_later($cb, $result)
180         } else {
181             # ..
182         }
183     }
184
185 =head2 EVENT SOURCES
186
187 An event source is responsible for producing events.  A source may produce
188 multiple events over its lifetime.
189
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.
195
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
199 example:
200
201   sub start_timer { 
202     my ($loops) = @_;
203
204     Amanda::MainLoop::timeout_source(200)->set_callback(sub {
205       my ($src) = @_;
206       print "timer\n";
207       if (--$loops <= 0) {
208         $src->remove();
209         Amanda::MainLoop::quit();
210       }
211     });
212   }
213   start_timer(10);
214   Amanda::MainLoop::run();
215
216 =head3 Timeout
217
218   my $src = Amanda::MainLoop::timeout_source(10000);
219
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
222 source is destroyed.
223
224 =head3 Idle
225
226   my $src = Amanda::MainLoop::idle_source(2);
227
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.
232
233 =head3 Child Watch
234
235   my $src = Amanda::MainLoop::child_watch_source($pid);
236
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.
241
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
246 possible situations.
247
248 =head3 File Descriptor
249
250   my $src = Amanda::MainLoop::fd_source($fd, G_IO_IN);
251
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
256 C<:GIOCondition>.
257
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>.
261
262 =head1 RELATION TO GLIB
263
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:
270
271 =over
272
273 =item Amanda's perl-accessible main loop only runs a single C<GMainContext>, and
274 always runs in the main thread.
275
276 =item Besides idle sources, event priorities are not accessible from Perl.
277
278 =back
279
280 =head1 PROGRAMMING HINTS
281
282 Most often, callbacks are short, and can be specified as anonymous subs:
283
284     $src->set_callback(sub {
285         my ($src) = @_;
286         # ...
287     });
288
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
292 anonymous) sub:
293
294     {
295         my $total_results = 0;
296
297         $src->set_callback(sub {
298             my ($src, $result) = @_;
299             $total_results += $result;
300         });
301     }
302
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:
307
308     {
309         my $op_src = long_operation_src();
310         my $timeout_src = Amanda::MainLoop::timeout_source($timeout);
311
312         sub finish {
313             $op_src->remove();
314             $timeout_src->remove();
315         }
316
317         $op_src->set_callback(sub {
318             print "Operation complete\n";
319             finish();
320         });
321
322         $timeout_src->set_callback(sub {
323             print "Operation timed out\n";
324             finish();
325         });
326     }
327
328 Both of these limitations may be lifted in future revisions of
329 L<Amanda::MainLoop>.
330
331 =cut
332
333 # glib's g_is_main_loop_running() seems inaccurate, so we just
334 # track that information locally..
335 my $mainloop_running = 0;
336
337 my @waiting_to_call_later;
338 sub call_later {
339     my ($sub, @args) = @_;
340
341     # add the callback if nothing is waiting right now
342     if (!@waiting_to_call_later) {
343         timeout_source(0)->set_callback(sub {
344             my ($src) = @_;
345             $src->remove();
346
347             while (@waiting_to_call_later) {
348                 my ($sub, @args) = @{pop @waiting_to_call_later};
349                 $sub->(@args);
350             }
351         });
352     }
353
354     push @waiting_to_call_later, [ $sub, @args ];
355 }
356
357 sub run {
358     $mainloop_running = 1;
359     run_c();
360     $mainloop_running = 0;
361 }
362
363 sub is_running {
364     return $mainloop_running;
365 }
366
367 push @EXPORT_OK, qw(GIOCondition_to_strings);
368 push @{$EXPORT_TAGS{"GIOCondition"}}, qw(GIOCondition_to_strings);
369
370 my %_GIOCondition_VALUES;
371 #Convert a flag value to a list of names for flags that are set.
372 sub GIOCondition_to_strings {
373     my ($flags) = @_;
374     my @result = ();
375
376     for my $k (keys %_GIOCondition_VALUES) {
377         my $v = $_GIOCondition_VALUES{$k};
378
379         #is this a matching flag?
380         if (($v == 0 && $flags == 0) || ($v != 0 && ($flags & $v) == $v)) {
381             push @result, $k;
382         }
383     }
384
385 #by default, just return the number as a 1-element list
386     if (!@result) {
387         return ($flags);
388     }
389
390     return @result;
391 }
392
393 push @EXPORT_OK, qw($G_IO_IN);
394 push @{$EXPORT_TAGS{"GIOCondition"}}, qw($G_IO_IN);
395
396 $_GIOCondition_VALUES{"G_IO_IN"} = $G_IO_IN;
397
398 push @EXPORT_OK, qw($G_IO_OUT);
399 push @{$EXPORT_TAGS{"GIOCondition"}}, qw($G_IO_OUT);
400
401 $_GIOCondition_VALUES{"G_IO_OUT"} = $G_IO_OUT;
402
403 push @EXPORT_OK, qw($G_IO_PRI);
404 push @{$EXPORT_TAGS{"GIOCondition"}}, qw($G_IO_PRI);
405
406 $_GIOCondition_VALUES{"G_IO_PRI"} = $G_IO_PRI;
407
408 push @EXPORT_OK, qw($G_IO_ERR);
409 push @{$EXPORT_TAGS{"GIOCondition"}}, qw($G_IO_ERR);
410
411 $_GIOCondition_VALUES{"G_IO_ERR"} = $G_IO_ERR;
412
413 push @EXPORT_OK, qw($G_IO_HUP);
414 push @{$EXPORT_TAGS{"GIOCondition"}}, qw($G_IO_HUP);
415
416 $_GIOCondition_VALUES{"G_IO_HUP"} = $G_IO_HUP;
417
418 push @EXPORT_OK, qw($G_IO_NVAL);
419 push @{$EXPORT_TAGS{"GIOCondition"}}, qw($G_IO_NVAL);
420
421 $_GIOCondition_VALUES{"G_IO_NVAL"} = $G_IO_NVAL;
422
423 #copy symbols in GIOCondition to constants
424 push @{$EXPORT_TAGS{"constants"}},  @{$EXPORT_TAGS{"GIOCondition"}};
425 1;