ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent/lib/AnyEvent/Util.pm
Revision: 1.1
Committed: Sun Apr 27 16:31:49 2008 UTC (16 years, 2 months ago) by root
Branch: MAIN
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 fork_eval);
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 { 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 { require EV::ADNS })
93 ? 2 : 1
94 }) - 1
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 (has_ev_adns) {
110 my $current = $Coro::current;
111 my @a;
112
113 EV::ADNS::submit ($_[0], &EV::ADNS::r_a, 0, sub {
114 (undef, undef, @a) = @_;
115 $cb->(@a ? Socket::inet_aton $a[0] : undef);
116 });
117 } else {
118 _do_asy $cb, sub { Socket::inet_aton $_[0] }, @_;
119 }
120 }
121
122 1;
123
124 =back
125
126 =head1 AUTHOR
127
128 Marc Lehmann <schmorp@schmorp.de>
129 http://home.schmorp.de/
130
131 =cut
132