ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent/lib/AnyEvent/Util.pm
Revision: 1.6
Committed: Fri May 2 15:36:10 2008 UTC (16 years, 2 months ago) by root
Branch: MAIN
Changes since 1.5: +23 -0 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 =head1 NAME
2
3 AnyEvent::Util - various utility functions.
4
5 =head1 SYNOPSIS
6
7 use AnyEvent::Util;
8
9 inet_aton $name, $cb->($ipn || undef);
10
11 =head1 DESCRIPTION
12
13 This module implements various utility functions, mostly replacing
14 well-known functions by event-ised counterparts.
15
16 =over 4
17
18 =cut
19
20 package AnyEvent::Util;
21
22 use strict;
23
24 no warnings "uninitialized";
25
26 use Socket ();
27
28 use AnyEvent;
29
30 use base 'Exporter';
31
32 #our @EXPORT = qw(gethostbyname gethostbyaddr);
33 our @EXPORT_OK = qw(inet_aton);
34
35 our $VERSION = '1.0';
36
37 our $MAXPARALLEL = 16; # max. number of parallel jobs
38
39 our $running;
40 our @queue;
41
42 sub _schedule;
43 sub _schedule {
44 return unless @queue;
45 return if $running >= $MAXPARALLEL;
46
47 ++$running;
48 my ($cb, $sub, @args) = @{shift @queue};
49
50 if (eval { local $SIG{__DIE__}; require POSIX }) {
51 my $pid = open my $fh, "-|";
52
53 if (!defined $pid) {
54 die "fork: $!";
55 } elsif (!$pid) {
56 syswrite STDOUT, join "\0", map { unpack "H*", $_ } $sub->(@args);
57 POSIX::_exit (0);
58 }
59
60 my $w; $w = AnyEvent->io (fh => $fh, poll => 'r', cb => sub {
61 --$running;
62 _schedule;
63 undef $w;
64
65 my $buf;
66 sysread $fh, $buf, 16384, length $buf;
67 $cb->(map { pack "H*", $_ } split /\0/, $buf);
68 });
69 } else {
70 $cb->($sub->(@args));
71 }
72 }
73
74 sub _do_asy {
75 push @queue, [@_];
76 _schedule;
77 }
78
79 sub dotted_quad($) {
80 $_[0] =~ /^(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9][0-9]?)
81 \.(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9][0-9]?)
82 \.(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9][0-9]?)
83 \.(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9][0-9]?)$/x
84 }
85
86 my $has_ev_adns;
87
88 sub has_ev_adns {
89 ($has_ev_adns ||= do {
90 my $model = AnyEvent::detect;
91 (($model eq "AnyEvent::Impl::CoroEV" or $model eq "AnyEvent::Impl::EV")
92 && eval { local $SIG{__DIE__}; require EV::ADNS })
93 ? 2 : 1 # so that || always detects as true
94 }) - 1 # 2 => true, 1 => false
95 }
96
97 =item AnyEvent::Util::inet_aton $name_or_address, $cb->($binary_address_or_undef)
98
99 Works almost exactly like its Socket counterpart, except that it uses a
100 callback.
101
102 =cut
103
104 sub inet_aton {
105 my ($name, $cb) = @_;
106
107 if (&dotted_quad) {
108 $cb->(Socket::inet_aton $name);
109 } elsif ($name eq "localhost") { # rfc2606 et al.
110 $cb->(v127.0.0.1);
111 } elsif (&has_ev_adns) {
112 EV::ADNS::submit ($name, &EV::ADNS::r_addr, 0, sub {
113 my (undef, undef, @a) = @_;
114 $cb->(@a ? Socket::inet_aton $a[0] : undef);
115 });
116 } else {
117 _do_asy $cb, sub { Socket::inet_aton $_[0] }, @_;
118 }
119 }
120
121 =item AnyEvent::Util::fh_nonblocking $fh, $nonblocking
122
123 Sets the blocking state of the given filehandle (true == nonblocking,
124 false == blocking). Uses fcntl on anything sensible and ioctl FIONBIO on
125 broken (i.e. windows) platforms.
126
127 =cut
128
129 sub fh_nonblocking($$) {
130 my ($fh, $nb) = @_;
131
132 require Fcntl;
133
134 if ($^O eq "MSWin32") {
135 $nb = (! ! $nb) + 0;
136 ioctl $fh, 0x8004667e, \$nb; # FIONBIO
137 } else {
138 fcntl $fh, &Fcntl::F_SETFL, $nb ? &Fcntl::O_NONBLOCK : 0;
139 }
140 }
141
142 1;
143
144 =back
145
146 =head1 AUTHOR
147
148 Marc Lehmann <schmorp@schmorp.de>
149 http://home.schmorp.de/
150
151 =cut
152