… | |
… | |
49 | |
49 | |
50 | use base 'Exporter'; |
50 | use base 'Exporter'; |
51 | |
51 | |
52 | @EXPORT = qw(loop unloop sweep); |
52 | @EXPORT = qw(loop unloop sweep); |
53 | |
53 | |
|
|
54 | BEGIN { |
54 | $VERSION = 0.45; |
55 | $VERSION = 0.45; |
|
|
56 | |
|
|
57 | require XSLoader; |
|
|
58 | XSLoader::load Coro::Event, $VERSION; |
|
|
59 | } |
55 | |
60 | |
56 | =item $w = Coro::Event->flavour(args...) |
61 | =item $w = Coro::Event->flavour(args...) |
57 | |
62 | |
58 | Create and return a watcher of the given type. |
63 | Create and return a watcher of the given type. |
59 | |
64 | |
… | |
… | |
76 | method. This is less efficient then calling the constructor once and the |
81 | method. This is less efficient then calling the constructor once and the |
77 | next method often, but it does save typing sometimes. |
82 | next method often, but it does save typing sometimes. |
78 | |
83 | |
79 | =cut |
84 | =cut |
80 | |
85 | |
81 | #Event->add_hooks(prepare => sub { |
|
|
82 | # &Coro::cede while &Coro::nready; |
|
|
83 | # 1e6; |
|
|
84 | #}); |
|
|
85 | |
|
|
86 | sub std_cb { |
86 | #sub std_cb { |
87 | my $w = $_[0]->w; |
87 | # my $w = $_[0]->w; |
88 | my $q = $w->private; |
88 | # my $q = $w->private; |
89 | $q->[1] = $_[0]; |
89 | # $q->[1] = $_[0]; |
90 | if ($q->[0]) { # somebody waiting? |
90 | # if ($q->[0]) { # somebody waiting? |
91 | $q->[0]->ready; |
91 | # $q->[0]->ready; |
92 | &Coro::schedule; |
92 | # &Coro::schedule; |
93 | } else { |
93 | # } else { |
94 | $w->stop; |
94 | # $w->stop; |
95 | } |
95 | # } |
96 | } |
96 | #} |
97 | |
97 | |
98 | for my $flavour (qw(idle var timer io signal)) { |
98 | for my $flavour (qw(idle var timer io signal)) { |
99 | push @EXPORT, "do_$flavour"; |
99 | push @EXPORT, "do_$flavour"; |
100 | my $new = \&{"Event::$flavour"}; |
100 | my $new = \&{"Event::$flavour"}; |
101 | my $class = "Coro::Event::$flavour"; |
101 | my $class = "Coro::Event::$flavour"; |
|
|
102 | my $type = $flavour eq "io" ? 1 : 0; |
102 | @{"${class}::ISA"} = (Coro::Event::, "Event::$flavour"); |
103 | @{"${class}::ISA"} = (Coro::Event::, "Event::$flavour"); |
103 | my $coronew = sub { |
104 | my $coronew = sub { |
104 | # how does one do method-call-by-name? |
105 | # how does one do method-call-by-name? |
105 | # my $w = $class->SUPER::$flavour(@_); |
106 | # my $w = $class->SUPER::$flavour(@_); |
106 | |
107 | |
… | |
… | |
109 | |
110 | |
110 | my $q = []; # [$coro, $event] |
111 | my $q = []; # [$coro, $event] |
111 | my $w = $new->( |
112 | my $w = $new->( |
112 | desc => $flavour, |
113 | desc => $flavour, |
113 | @_, |
114 | @_, |
114 | cb => \&std_cb, |
115 | parked => 1, |
115 | ); |
116 | ); |
116 | $w->private($q); # using private as attribute is pretty useless... |
117 | _install_std_cb($w, $type); |
117 | bless $w, $class; # reblessing due to broken Event |
118 | bless $w, $class; # reblessing due to broken Event |
118 | }; |
119 | }; |
119 | *{ $flavour } = $coronew; |
120 | *{ $flavour } = $coronew; |
120 | *{"do_$flavour"} = sub { |
121 | *{"do_$flavour"} = sub { |
121 | unshift @_, Coro::Event::; |
122 | unshift @_, Coro::Event::; |
… | |
… | |
123 | $e->w->cancel; |
124 | $e->w->cancel; |
124 | $e; |
125 | $e; |
125 | }; |
126 | }; |
126 | } |
127 | } |
127 | |
128 | |
|
|
129 | # double calls to avoid stack-cloning ;() |
|
|
130 | # is about 20% slower, though. |
|
|
131 | sub next($) { |
|
|
132 | &_next0; |
|
|
133 | &Coro::schedule; |
|
|
134 | &_next1; |
|
|
135 | } |
|
|
136 | |
128 | sub next { |
137 | #sub next { |
129 | my $w = $_[0]; |
138 | # my $w = $_[0]; |
130 | my $q = $w->private; |
139 | # my $q = $w->private; |
131 | if ($q->[1]) { # event waiting? |
140 | # if ($q->[1]) { # event waiting? |
132 | $w->again unless $w->is_cancelled; |
141 | # $w->again unless $w->is_cancelled; |
133 | } elsif ($q->[0]) { |
142 | # } elsif ($q->[0]) { |
134 | croak "only one coroutine can wait for an event"; |
143 | # croak "only one coroutine can wait for an event"; |
135 | } else { |
144 | # } else { |
136 | local $q->[0] = $Coro::current; |
145 | # local $q->[0] = $Coro::current; |
137 | &Coro::schedule; |
146 | # &Coro::schedule; |
138 | } |
147 | # } |
139 | pop @$q; |
148 | # pop @$q; |
140 | } |
149 | #} |
|
|
150 | |
|
|
151 | sub Coro::Event::Ev::w { $_[0][2] } |
|
|
152 | sub Coro::Event::Ev::got { $_[0][3] } |
|
|
153 | sub Coro::Event::Ev::prio { croak "prio not supported yet, please mail to pcg\@goof.com" } |
|
|
154 | sub Coro::Event::Ev::hits { croak "prio not supported yet, please mail to pcg\@goof.com" } |
141 | |
155 | |
142 | =item sweep |
156 | =item sweep |
143 | |
157 | |
144 | Similar to Event::one_event and Event::sweep: The idle task is called once |
158 | Similar to Event::one_event and Event::sweep: The idle task is called once |
145 | (this has the effect of jumping back into the Event loop once to serve new |
159 | (this has the effect of jumping back into the Event loop once to serve new |