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 |
|
|
|