ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro/Select.pm
Revision: 1.4
Committed: Fri Apr 25 04:28:50 2008 UTC (16 years, 1 month ago) by root
Branch: MAIN
CVS Tags: rel-4_71, rel-4_7
Changes since 1.3: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 =head1 NAME
2
3 Coro::Select - a (slow but coro-aware) replacement for CORE::select
4
5 =head1 SYNOPSIS
6
7 use Coro::Select; # replace select globally
8 use Core::Select 'select'; # only in this module
9 use Coro::Select (); # use Coro::Select::select
10
11 =head1 DESCRIPTION
12
13 This module tries to create a fully working replacement for perl's
14 C<select> built-in, using C<AnyEvent> watchers to do the job, so other
15 coroutines can run in parallel to any select user. As many libraries that
16 only have a blocking API do not use global variables and often use select
17 (or IO::Select), this effectively makes most such libraries "somewhat"
18 non-blocking w.r.t. other coroutines.
19
20 To be effective globally, this module must be C<use>'d before any other
21 module that uses C<select>, so it should generally be the first module
22 C<use>'d in the main program.
23
24 You can also invoke it from the commandline as C<perl -MCoro::Select>.
25
26 Performance naturally isn't great, but unless you need very high select
27 performance you normally won't notice the difference.
28
29 =over 4
30
31 =cut
32
33 package Coro::Select;
34
35 use strict;
36
37 use Event;
38
39 use Coro;
40 use AnyEvent;
41
42 use base Exporter::;
43
44 our $VERSION = 4.6;
45 our @EXPORT_OK = "select";
46
47 sub import {
48 my $pkg = shift;
49 if (@_) {
50 $pkg->export (scalar caller 0, @_);
51 } else {
52 $pkg->export ("CORE::GLOBAL", "select");
53 }
54 }
55
56 sub select(;*$$$) { # not the correct prototype, but well... :()
57 if (@_ == 0) {
58 return CORE::select
59 } elsif (@_ == 1) {
60 return CORE::select $_[0]
61 } elsif (defined $_[3] && !$_[3]) {
62 return CORE::select $_[0], $_[1], $_[2], $_[3]
63 } else {
64 my $current = $Coro::current;
65 my $nfound = 0;
66 my @w;
67 # AnyEvent does not do 'e', so replace it by 'r'
68 for ([0, 'r', '<'], [1, 'w', '>'], [2, 'r', '<']) {
69 my ($i, $poll, $mode) = @$_;
70 if (defined (my $vec = $_[$i])) {
71 my $rvec = \$_[$i];
72 for my $b (0 .. (8 * length $vec)) {
73 if (vec $vec, $b, 1) {
74 (vec $$rvec, $b, 1) = 0;
75 open my $fh, "$mode&$b"
76 or die "Coro::Select::fd2fh($b): $!";
77 push @w,
78 AnyEvent->io (fh => $fh, poll => $poll, cb => sub {
79 (vec $$rvec, $b, 1) = 1;
80 $nfound++;
81 $current->ready;
82 undef $current;
83 });
84 }
85 }
86 }
87 }
88
89 push @w,
90 AnyEvent->timer (after => $_[3], cb => sub {
91 $current->ready;
92 undef $current;
93 })
94 if defined $_[3];
95
96 # wait here
97 &Coro::schedule;
98 &Coro::schedule while $current;
99
100 return $nfound
101 }
102 }
103
104 1;
105
106 =back
107
108 =head1 SEE ALSO
109
110 L<Coro::LWP>.
111
112 =head1 AUTHOR
113
114 Marc Lehmann <schmorp@schmorp.de>
115 http://home.schmorp.de/
116
117 =cut
118
119