ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-DBus/DBus.pm
Revision: 1.4
Committed: Mon Jun 21 00:12:52 2010 UTC (13 years, 10 months ago) by root
Branch: MAIN
CVS Tags: rel-0_1
Changes since 1.3: +4 -4 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 =head1 NAME
2
3 AnyEvent::AIO - truly asynchronous file and directory I/O
4
5 =head1 SYNOPSIS
6
7 use AnyEvent::DBus;
8
9 # now use the Net::DBus API, preferably the non-blocking variants
10
11 =head1 DESCRIPTION
12
13 This module is an L<AnyEvent> user, you need to make sure that you use and
14 run a supported event loop.
15
16 Loading this module will install the necessary magic to seamlessly
17 integrate L<Net::DBus> into L<AnyEvent>. It does this by quite brutally
18 hacking L<Net::DBus::Reactor> so that all dbus connections created after
19 loading this module will automatically be managed by this module.
20
21 Note that a) a lot inside Net::DBus is still blocking b) if you call a
22 method that blocks, you again block your process (basically anything
23 but calls to the Net::DBus::Binding::Connection objects block, but
24 see Net::DBus::Annoation, specifically dbus_call_async) and c) this
25 module only implements the minimum API required to make Net::DBus work -
26 Net::DBus unfortunately has no nice hooking API.
27
28 However, unlike L<Net::DBus::Reactor>, this module should be fully
29 non-blocking as long as you only use non-blocking APIs (Net::DBus::Reactor
30 blocks on writes). It should also be faster, but Net::DBus is such a
31 morass os unneeded method calls that speed won't matter much...
32
33 =head2 EXAMPLE
34
35 Here is a simple example. Both work with AnyEvent::DBus and do the same
36 thing, but only the second is actually non-blocking.
37
38 Example 1: list registered named, blocking version.
39
40 use AnyEvent::DBus;
41
42 my $conn = Net::DBus->find;
43 my $bus = $conn->get_bus_object;
44
45 for my $name (@{ $bus->ListNames }) {
46 print " $name\n";
47 }
48
49 Example 1: list registered named, somewhat non-blocking version.
50
51 use AnyEvent;
52 use AnyEvent::DBus;
53 use Net::DBus::Annotation qw(:call);
54
55 my $conn = Net::DBus->find; # always blocks :/
56 my $bus = $conn->get_bus_object;
57
58 my $quit = AE::cv;
59
60 # the trick here is to prepend dbus_call_async to any method
61 # arguments and then to call the set_notify method on the
62 # returned Net::DBus::AsyncReply object
63
64 $bus->ListNames (dbus_call_async)->set_notify (sub {
65 for my $name (@{ $_[0]->get_result }) {
66 print " $name\n";
67 }
68 $quit->send;
69 });
70
71 $quit->recv;
72
73 =cut
74
75 package AnyEvent::DBus;
76
77 use common::sense;
78
79 use AnyEvent ();
80 use Net::DBus ();
81 use Net::DBus::Binding::Watch ();
82
83 our $VERSION = '0.1';
84
85 # yup, Net::DBus checks by using exists on %INC...
86 $INC{'Net/DBus/Reactor.pm'} = undef;
87
88 # claim we are the main reactor mainloop
89 *Net::DBus::Reactor::main = sub { __PACKAGE__ };
90
91 our $I = 0;
92 our %O; # watchers and timers, unfortunately, dbus only supports attaching integers...
93
94 sub watch_off {
95 delete $O{$_[1]->get_data};
96 }
97
98 sub io_toggle {
99 my ($con, $w) = @_;
100
101 my $id = $w->get_data;
102 my $f = $w->get_flags;
103 my $fd = $w->get_fileno;
104 my $on = $w->is_enabled;
105
106 $f & Net::DBus::Binding::Watch::READABLE ()
107 and
108 $O{$id}[0] = $on && AE::io $fd, 0, sub {
109 $w->handle (Net::DBus::Binding::Watch::READABLE ());
110 $con->dispatch; # wtf., we tell it data is ready, but have to call dispatch ourselves???
111 };
112
113 $f & Net::DBus::Binding::Watch::WRITABLE ()
114 and
115 $O{$id}[1] = $on && AE::io $fd, 1, sub {
116 $w->handle (Net::DBus::Binding::Watch::WRITABLE ());
117 # calling flush, as NEt::DBus::Reactor does, is blocking :/
118 };
119 }
120
121 sub io_on {
122 my ($con, $w) = @_;
123
124 my $id = ++$I;
125 $w->set_data ($id);
126
127 &io_toggle;
128 }
129
130 sub timeout_toggle {
131 my ($con, $w) = @_;
132
133 my $id = $w->get_data;
134 my $i = $w->get_interval * 0.001;
135
136 $O{$id} = $w->is_enabled && AE::timer $i, $i, sub { $w->handle };
137 }
138
139 sub timeout_on {
140 my ($con, $w) = @_;
141 my $id = ++$I;
142 $w->set_data ($id);
143
144 &timeout_toggle;
145 }
146
147 sub manage {
148 my (undef, $con) = @_;
149
150 $con->set_watch_callbacks (\&io_on, \&watch_off, \&io_toggle);
151 # if $con->can ("set_watch_callbacks");
152
153 $con->set_timeout_callbacks (\&timeout_on, \&watch_off, \&timeout_toggle);
154 # if $con->can ("set_timeout_callbacks");
155 }
156
157 =head1 SEE ALSO
158
159 L<AnyEvent>, L<Net::DBus>.
160
161 =head1 AUTHOR
162
163 Marc Lehmann <schmorp@schmorp.de>
164 http://home.schmorp.de/
165
166 =cut
167
168 1