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

# User Rev Content
1 root 1.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 root 1.2 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 root 1.1
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 root 1.4 $con->set_watch_callbacks (\&io_on, \&watch_off, \&io_toggle);
151     # if $con->can ("set_watch_callbacks");
152 root 1.3
153 root 1.4 $con->set_timeout_callbacks (\&timeout_on, \&watch_off, \&timeout_toggle);
154     # if $con->can ("set_timeout_callbacks");
155 root 1.1 }
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