ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent/lib/AnyEvent/Impl/Glib.pm
Revision: 1.34
Committed: Thu Aug 28 11:47:09 2014 UTC (9 years, 8 months ago) by root
Branch: MAIN
CVS Tags: rel-7_08, rel-7_09, rel-7_16, rel-7_13, rel-7_11, rel-7_15, rel-7_14, rel-7_12, HEAD
Changes since 1.33: +37 -8 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.12 =head1 NAME
2    
3     AnyEvent::Impl::Glib - AnyEvent adaptor for Glib
4    
5     =head1 SYNOPSIS
6    
7 root 1.16 use AnyEvent;
8     use Glib;
9    
10     # this module gets loaded automatically as required
11 root 1.12
12     =head1 DESCRIPTION
13    
14     This module provides transparent support for AnyEvent. You don't have to
15     do anything to make Glib work with AnyEvent except by loading Glib before
16     creating the first AnyEvent watcher.
17    
18     Glib is probably the most inefficient event loop that has ever seen the
19 root 1.20 light of the world: Glib not only scans all its watchers (really, ALL of
20     them, whether I/O-related, timer-related or what not) during each loop
21 root 1.12 iteration, it also does so multiple times and rebuilds the poll list for
22 root 1.34 the kernel each time again, dynamically even. Newer versions of libglib
23     fortunately do not call malloc/free on every single watcher invocation,
24     though.
25    
26     Glib also enforces certain undocumented behaviours, for example, you
27     cannot always remove active child watchers, and the conditions on when
28     it is valid to do so are not documented. Of course, if you get it wrong,
29     you get "GLib-CRITICAL" messages. This makes it extremely hard to write
30     "correct" glib programs, as you have to study the source code to get it
31     right, and hope future versions don't change any internals.
32 root 1.12
33 root 1.34 AnyEvent implements the necessary workarounds, at a small performance
34     cost.
35    
36     On the positive side, and most importantly, when it works, Glib generally
37     works correctly, no quarrels there.
38 root 1.20
39 root 1.12 If you create many watchers (as in: more than two), you might consider one
40     of the L<Glib::EV>, L<EV::Glib> or L<Glib::Event> modules that map Glib to
41     other, more efficient, event loops.
42    
43 root 1.21 This module uses the default Glib main context for all its watchers.
44 root 1.12
45     =cut
46    
47 root 1.1 package AnyEvent::Impl::Glib;
48    
49 root 1.25 use AnyEvent (); BEGIN { AnyEvent::common_sense }
50 root 1.28 use Glib 1.210 (); # (stable 1.220 2009, also Glib 2.4+ required, 2004)
51 root 1.1
52 root 1.22 our $mainloop = Glib::MainContext->default;
53 root 1.1
54 root 1.24 my %io_cond = (
55     r => ["in" , "hup"],
56     w => ["out", "hup"],
57     );
58    
59 root 1.2 sub io {
60     my ($class, %arg) = @_;
61    
62 root 1.17 my $cb = $arg{cb};
63 root 1.24 my $fd = fileno $arg{fh};
64     defined $fd or $fd = $arg{fh};
65 root 1.2
66 root 1.24 my $source = add_watch Glib::IO
67     $fd,
68     $io_cond{$arg{poll}},
69     sub { &$cb; 1 };
70 root 1.2
71 root 1.17 bless \\$source, $class
72 root 1.1 }
73    
74 root 1.2 sub timer {
75     my ($class, %arg) = @_;
76 root 1.1
77 root 1.18 my $cb = $arg{cb};
78     my $ival = $arg{interval} * 1000;
79 root 1.1
80 root 1.26 my $source; $source = add Glib::Timeout $arg{after} < 0 ? 0 : $arg{after} * 1000,
81 root 1.18 $ival ? sub {
82     remove Glib::Source $source;
83     $source = add Glib::Timeout $ival, sub { &$cb; 1 };
84     &$cb;
85 root 1.34 1 # already removed, should be a nop
86 root 1.18 }
87 root 1.34 : sub {
88     # due to the braindamaged libglib API (it manages
89     # removed-but-active watchers internally, but forces
90     # users to # manage the same externally as well),
91     # we have to go through these contortions.
92     remove Glib::Source $source;
93     undef $source;
94     &$cb;
95     1 # already removed, should be a nop
96     };
97 root 1.1
98 root 1.17 bless \\$source, $class
99 root 1.1 }
100    
101 root 1.21 sub idle {
102     my ($class, %arg) = @_;
103    
104     my $cb = $arg{cb};
105     my $source = add Glib::Idle sub { &$cb; 1 };
106 root 1.28
107 root 1.21 bless \\$source, $class
108     }
109    
110 root 1.6 sub DESTROY {
111 root 1.34 remove Glib::Source $${$_[0]}
112     if defined $${$_[0]};
113 root 1.2 }
114    
115 root 1.28 our %pid_w;
116     our %pid_cb;
117    
118     sub child {
119     my ($class, %arg) = @_;
120    
121     $arg{pid} > 0
122     or Carp::croak "Glib does not support watching for all pids (pid == 0) as attempted";
123    
124     my $pid = $arg{pid};
125     my $cb = $arg{cb};
126    
127     $pid_cb{$pid}{$cb+0} = $cb;
128    
129     $pid_w{$pid} ||= Glib::Child->watch_add ($pid, sub {
130 root 1.34 # the unbelievably braindamaged glib api ignores the return
131     # value and always removes the watcher (this is of course
132     # undocumented), so we need to go through these contortions to
133     # work around this, here and in DESTROY.
134     undef $pid_w{$pid};
135    
136 root 1.28 $_->($_[0], $_[1])
137     for values %{ $pid_cb{$pid} };
138    
139 root 1.34 1 # gets ignored
140 root 1.28 });
141    
142     bless [$pid, $cb+0], "AnyEvent::Impl::Glib::child"
143     }
144    
145     sub AnyEvent::Impl::Glib::child::DESTROY {
146     my ($pid, $icb) = @{ $_[0] };
147    
148     delete $pid_cb{$pid}{$icb};
149     unless (%{ $pid_cb{$pid} }) {
150     delete $pid_cb{$pid};
151 root 1.34 my $source = delete $pid_w{$pid};
152     remove Glib::Source if defined $source;
153 root 1.28 }
154     }
155    
156 root 1.27 #sub loop {
157     # # hackish, but we do not have a mainloop, just a maincontext
158     # $mainloop->iteration (1) while 1;
159     #}
160 root 1.7
161 root 1.29 sub _poll {
162     $mainloop->iteration (1);
163     }
164    
165     sub AnyEvent::CondVar::Base::_wait {
166 root 1.30 $mainloop->iteration (1) until exists $_[0]{_ae_sent};
167 root 1.29 }
168    
169 root 1.12 =head1 SEE ALSO
170    
171 root 1.14 L<AnyEvent>, L<Glib>.
172 root 1.12
173     =head1 AUTHOR
174    
175     Marc Lehmann <schmorp@schmorp.de>
176 root 1.33 http://anyevent.schmorp.de
177 root 1.12
178     =cut
179 root 1.1
180 root 1.31 1
181