ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro/Select.pm
Revision: 1.6
Committed: Thu May 29 03:31:52 2008 UTC (16 years ago) by root
Branch: MAIN
CVS Tags: rel-4_73
Changes since 1.5: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.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 root 1.2 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 root 1.1
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 root 1.2 Performance naturally isn't great, but unless you need very high select
27     performance you normally won't notice the difference.
28    
29 root 1.1 =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 root 1.6 our $VERSION = 4.73;
45 root 1.1 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 root 1.3 undef $current;
83 root 1.1 });
84     }
85     }
86     }
87     }
88    
89     push @w,
90     AnyEvent->timer (after => $_[3], cb => sub {
91     $current->ready;
92 root 1.3 undef $current;
93 root 1.1 })
94     if defined $_[3];
95    
96     # wait here
97 root 1.3 &Coro::schedule;
98     &Coro::schedule while $current;
99 root 1.1
100     return $nfound
101     }
102     }
103    
104     1;
105    
106     =back
107    
108 root 1.2 =head1 SEE ALSO
109    
110     L<Coro::LWP>.
111    
112 root 1.1 =head1 AUTHOR
113    
114     Marc Lehmann <schmorp@schmorp.de>
115     http://home.schmorp.de/
116    
117     =cut
118    
119