ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent/lib/AnyEvent/Util.pm
Revision: 1.30
Committed: Mon May 26 02:30:33 2008 UTC (16 years, 1 month ago) by root
Branch: MAIN
Changes since 1.29: +8 -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 =head1 DESCRIPTION
10
11 This module implements various utility functions, mostly replacing
12 well-known functions by event-ised counterparts.
13
14 All functions documented without C<AnyEvent::Util::> prefix are exported
15 by default.
16
17 =over 4
18
19 =cut
20
21 package AnyEvent::Util;
22
23 no warnings;
24 use strict;
25
26 use Carp ();
27 use Errno ();
28 use Socket ();
29
30 use AnyEvent ();
31
32 use base 'Exporter';
33
34 BEGIN {
35 *socket_inet_aton = \&Socket::inet_aton; # take a copy, in case Coro::LWP overrides it
36 }
37
38 BEGIN {
39 my $af_inet6 = eval { &Socket::AF_INET6 };
40
41 # uhoh
42 $af_inet6 ||= 10 if $^O =~ /linux/;
43 $af_inet6 ||= 23 if $^O =~ /cygwin|mswin32/i;
44 $af_inet6 ||= 24 if $^O =~ /openbsd|netbsd/;
45 $af_inet6 ||= 28 if $^O =~ /freebsd/;
46
47 $af_inet6 && socket my $ipv6_socket, $af_inet6, &Socket::SOCK_STREAM, 0 # check if they can be created
48 or $af_inet6 = 0;
49
50 eval "sub AF_INET6() { $af_inet6 }"; die if $@;
51
52 delete $AnyEvent::PROTOCOL{ipv6} unless $af_inet6;
53 }
54
55 BEGIN {
56 # broken windows perls use undocumented error codes...
57 if ($^O =~ /mswin32/i) {
58 eval "sub WSAWOULDBLOCK() { 10035 }";
59 eval "sub WSAEINPROGRESS() { 10036 }";
60 } else {
61 eval "sub WSAWOULDBLOCK() { -1e99 }"; # should never match any errno value
62 eval "sub WSAEINPROGRESS() { -1e99 }"; # should never match any errno value
63 }
64 }
65
66 our @EXPORT = qw(fh_nonblocking guard);
67 our @EXPORT_OK = qw(AF_INET6 WSAWOULDBLOCK WSAEINPROGRESS);
68
69 our $VERSION = '1.0';
70
71 our $MAXPARALLEL = 16; # max. number of parallel jobs
72
73 our $running;
74 our @queue;
75
76 sub _schedule;
77 sub _schedule {
78 return unless @queue;
79 return if $running >= $MAXPARALLEL;
80
81 ++$running;
82 my ($cb, $sub, @args) = @{shift @queue};
83
84 if (eval { local $SIG{__DIE__}; require POSIX }) {
85 my $pid = open my $fh, "-|";
86
87 if (!defined $pid) {
88 die "fork: $!";
89 } elsif (!$pid) {
90 syswrite STDOUT, join "\0", map { unpack "H*", $_ } $sub->(@args);
91 POSIX::_exit (0);
92 }
93
94 my $w; $w = AnyEvent->io (fh => $fh, poll => 'r', cb => sub {
95 --$running;
96 _schedule;
97 undef $w;
98
99 my $buf;
100 sysread $fh, $buf, 16384, length $buf;
101 $cb->(map { pack "H*", $_ } split /\0/, $buf);
102 });
103 } else {
104 $cb->($sub->(@args));
105 }
106 }
107
108 sub _do_asy {
109 push @queue, [@_];
110 _schedule;
111 }
112
113 # to be removed
114 sub dotted_quad($) {
115 $_[0] =~ /^(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9][0-9]?)
116 \.(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9][0-9]?)
117 \.(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9][0-9]?)
118 \.(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9][0-9]?)$/x
119 }
120
121 # just a forwarder
122 sub inet_aton {
123 require AnyEvent::Socket;
124 *inet_aton = \&AnyEvent::Socket::inet_aton;
125 goto &inet_aton
126 }
127
128 =item fh_nonblocking $fh, $nonblocking
129
130 Sets the blocking state of the given filehandle (true == nonblocking,
131 false == blocking). Uses fcntl on anything sensible and ioctl FIONBIO on
132 broken (i.e. windows) platforms.
133
134 =cut
135
136 sub fh_nonblocking($$) {
137 my ($fh, $nb) = @_;
138
139 require Fcntl;
140
141 if ($^O eq "MSWin32") {
142 $nb = (! ! $nb) + 0;
143 ioctl $fh, 0x8004667e, \$nb; # FIONBIO
144 } else {
145 fcntl $fh, &Fcntl::F_SETFL, $nb ? &Fcntl::O_NONBLOCK : 0;
146 }
147 }
148
149 =item $guard = guard { CODE }
150
151 This function creates a special object that, when called, will execute the
152 code block.
153
154 This is often handy in continuation-passing style code to clean up some
155 resource regardless of where you break out of a process.
156
157 You can call one method on the returned object:
158
159 =item $guard->cancel
160
161 This simply causes the code block not to be invoked: it "cancels" the
162 guard.
163
164 =cut
165
166 sub AnyEvent::Util::Guard::DESTROY {
167 ${$_[0]}->();
168 }
169
170 sub AnyEvent::Util::Guard::cancel($) {
171 ${$_[0]} = sub { };
172 }
173
174 sub guard(&) {
175 bless \(my $cb = shift), AnyEvent::Util::Guard::
176 }
177
178 1;
179
180 =back
181
182 =head1 AUTHOR
183
184 Marc Lehmann <schmorp@schmorp.de>
185 http://home.schmorp.de/
186
187 =cut
188