ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent/lib/AnyEvent/Impl/Glib.pm
(Generate patch)

Comparing AnyEvent/lib/AnyEvent/Impl/Glib.pm (file contents):
Revision 1.23 by root, Mon Jun 22 11:17:03 2009 UTC vs.
Revision 1.34 by root, Thu Aug 28 11:47:09 2014 UTC

17 17
18Glib is probably the most inefficient event loop that has ever seen the 18Glib is probably the most inefficient event loop that has ever seen the
19light of the world: Glib not only scans all its watchers (really, ALL of 19light of the world: Glib not only scans all its watchers (really, ALL of
20them, whether I/O-related, timer-related or what not) during each loop 20them, whether I/O-related, timer-related or what not) during each loop
21iteration, it also does so multiple times and rebuilds the poll list for 21iteration, it also does so multiple times and rebuilds the poll list for
22the kernel each time again, dynamically even. 22the kernel each time again, dynamically even. Newer versions of libglib
23fortunately do not call malloc/free on every single watcher invocation,
24though.
23 25
26Glib also enforces certain undocumented behaviours, for example, you
27cannot always remove active child watchers, and the conditions on when
28it is valid to do so are not documented. Of course, if you get it wrong,
29you 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
31right, and hope future versions don't change any internals.
32
33AnyEvent implements the necessary workarounds, at a small performance
34cost.
35
24On the positive side, and most importantly, Glib generally works 36On the positive side, and most importantly, when it works, Glib generally
25correctly, no quarrels there. 37works correctly, no quarrels there.
26 38
27If you create many watchers (as in: more than two), you might consider one 39If you create many watchers (as in: more than two), you might consider one
28of the L<Glib::EV>, L<EV::Glib> or L<Glib::Event> modules that map Glib to 40of the L<Glib::EV>, L<EV::Glib> or L<Glib::Event> modules that map Glib to
29other, more efficient, event loops. 41other, more efficient, event loops.
30 42
32 44
33=cut 45=cut
34 46
35package AnyEvent::Impl::Glib; 47package AnyEvent::Impl::Glib;
36 48
37no warnings; 49use AnyEvent (); BEGIN { AnyEvent::common_sense }
38use strict; 50use Glib 1.210 (); # (stable 1.220 2009, also Glib 2.4+ required, 2004)
39
40use Glib ();
41 51
42our $mainloop = Glib::MainContext->default; 52our $mainloop = Glib::MainContext->default;
53
54my %io_cond = (
55 r => ["in" , "hup"],
56 w => ["out", "hup"],
57);
43 58
44sub io { 59sub io {
45 my ($class, %arg) = @_; 60 my ($class, %arg) = @_;
46 61
47 my $cb = $arg{cb}; 62 my $cb = $arg{cb};
63 my $fd = fileno $arg{fh};
64 defined $fd or $fd = $arg{fh};
48 65
49 my @cond; 66 my $source = add_watch Glib::IO
50 # some glibs need hup, others error with it, YMMV 67 $fd,
51 push @cond, "in", "hup" if $arg{poll} eq "r"; 68 $io_cond{$arg{poll}},
52 push @cond, "out", "hup" if $arg{poll} eq "w"; 69 sub { &$cb; 1 };
53 70
54 my $source = add_watch Glib::IO fileno $arg{fh}, \@cond, sub { &$cb; 1 };
55 bless \\$source, $class 71 bless \\$source, $class
56} 72}
57 73
58sub timer { 74sub timer {
59 my ($class, %arg) = @_; 75 my ($class, %arg) = @_;
60 76
61 my $cb = $arg{cb}; 77 my $cb = $arg{cb};
62 my $ival = $arg{interval} * 1000; 78 my $ival = $arg{interval} * 1000;
63 79
64 my $source; $source = add Glib::Timeout $arg{after} * 1000, 80 my $source; $source = add Glib::Timeout $arg{after} < 0 ? 0 : $arg{after} * 1000,
65 $ival ? sub { 81 $ival ? sub {
66 remove Glib::Source $source; 82 remove Glib::Source $source;
67 $source = add Glib::Timeout $ival, sub { &$cb; 1 }; 83 $source = add Glib::Timeout $ival, sub { &$cb; 1 };
68 &$cb; 84 &$cb;
69 0 85 1 # already removed, should be a nop
70 } 86 }
71 : sub { &$cb; 0 }; 87 : 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 };
72 97
73 bless \\$source, $class 98 bless \\$source, $class
74} 99}
75 100
76sub idle { 101sub idle {
77 my ($class, %arg) = @_; 102 my ($class, %arg) = @_;
78 103
79 my $cb = $arg{cb}; 104 my $cb = $arg{cb};
80 my $source = add Glib::Idle sub { &$cb; 1 }; 105 my $source = add Glib::Idle sub { &$cb; 1 };
106
81 bless \\$source, $class 107 bless \\$source, $class
82} 108}
83 109
84sub DESTROY { 110sub DESTROY {
85 remove Glib::Source $${$_[0]}; 111 remove Glib::Source $${$_[0]}
112 if defined $${$_[0]};
86} 113}
87 114
88sub one_event { 115our %pid_w;
116our %pid_cb;
117
118sub 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 # 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 $_->($_[0], $_[1])
137 for values %{ $pid_cb{$pid} };
138
139 1 # gets ignored
140 });
141
142 bless [$pid, $cb+0], "AnyEvent::Impl::Glib::child"
143}
144
145sub 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 my $source = delete $pid_w{$pid};
152 remove Glib::Source if defined $source;
153 }
154}
155
156#sub loop {
157# # hackish, but we do not have a mainloop, just a maincontext
158# $mainloop->iteration (1) while 1;
159#}
160
161sub _poll {
89 $mainloop->iteration (1); 162 $mainloop->iteration (1);
90} 163}
91 164
92sub loop { 165sub AnyEvent::CondVar::Base::_wait {
93 $mainloop->iteration (1) while 1; # hackish, but w ehave no mainloop 166 $mainloop->iteration (1) until exists $_[0]{_ae_sent};
94} 167}
95
961;
97 168
98=head1 SEE ALSO 169=head1 SEE ALSO
99 170
100L<AnyEvent>, L<Glib>. 171L<AnyEvent>, L<Glib>.
101 172
102=head1 AUTHOR 173=head1 AUTHOR
103 174
104 Marc Lehmann <schmorp@schmorp.de> 175 Marc Lehmann <schmorp@schmorp.de>
105 http://home.schmorp.de/ 176 http://anyevent.schmorp.de
106 177
107=cut 178=cut
108 179
1801
181

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines