ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-DBus/DBus.pm
Revision: 1.5
Committed: Mon Jun 21 10:24:44 2010 UTC (13 years, 10 months ago) by root
Branch: MAIN
CVS Tags: rel-0_3
Changes since 1.4: +14 -3 lines
Log Message:
0.3

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     $con->dispatch; # wtf., we tell it data is ready, but have to call dispatch ourselves???
122     };
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     # calling flush, as NEt::DBus::Reactor does, is blocking :/
129     };
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     $O{$id} = $w->is_enabled && AE::timer $i, $i, sub { $w->handle };
148     }
149    
150     sub timeout_on {
151     my ($con, $w) = @_;
152     my $id = ++$I;
153     $w->set_data ($id);
154    
155     &timeout_toggle;
156     }
157    
158     sub manage {
159     my (undef, $con) = @_;
160    
161 root 1.4 $con->set_watch_callbacks (\&io_on, \&watch_off, \&io_toggle);
162     # if $con->can ("set_watch_callbacks");
163 root 1.3
164 root 1.4 $con->set_timeout_callbacks (\&timeout_on, \&watch_off, \&timeout_toggle);
165     # if $con->can ("set_timeout_callbacks");
166 root 1.1 }
167    
168     =head1 SEE ALSO
169    
170     L<AnyEvent>, L<Net::DBus>.
171    
172     =head1 AUTHOR
173    
174     Marc Lehmann <schmorp@schmorp.de>
175     http://home.schmorp.de/
176    
177     =cut
178    
179     1