ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-DBus/DBus.pm
Revision: 1.6
Committed: Mon Jun 21 19:43:42 2010 UTC (13 years, 10 months ago) by root
Branch: MAIN
Changes since 1.5: +6 -3 lines
Log Message:
*** empty log message ***

File Contents

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