ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro.pm
(Generate patch)

Comparing Coro/Coro.pm (file contents):
Revision 1.8 by root, Sat Jul 14 22:14:21 2001 UTC vs.
Revision 1.17 by root, Thu Jul 19 02:45:09 2001 UTC

18 18
19 yield; 19 yield;
20 20
21=head1 DESCRIPTION 21=head1 DESCRIPTION
22 22
23This module collection manages coroutines. Coroutines are similar to
24Threads but don't run in parallel.
25
26This module is still experimental, see the BUGS section below.
27
23=cut 28=cut
24 29
25package Coro; 30package Coro;
26 31
27use Coro::State; 32use Coro::State;
28 33
29use base Exporter; 34use base Exporter;
30 35
31$VERSION = 0.03; 36$VERSION = 0.08;
32 37
33@EXPORT = qw(async yield schedule); 38@EXPORT = qw(async yield schedule terminate);
34@EXPORT_OK = qw($current); 39@EXPORT_OK = qw($current);
35 40
36{ 41{
37 use subs 'async'; 42 use subs 'async';
38 43
47 my @attrs; 52 my @attrs;
48 for (@_) { 53 for (@_) {
49 if ($_ eq "Coro") { 54 if ($_ eq "Coro") {
50 push @async, $ref; 55 push @async, $ref;
51 } else { 56 } else {
52 push @attrs, @_; 57 push @attrs, $_;
53 } 58 }
54 } 59 }
55 return $old ? $old->($package, $name, @attrs) : @attrs; 60 return $old ? $old->($package, $ref, @attrs) : @attrs;
56 }; 61 };
57 } 62 }
58 63
59 sub INIT { 64 sub INIT {
60 async pop @async while @async; 65 async pop @async while @async;
61 } 66 }
62} 67}
63 68
64my $idle = new Coro sub {
65 &yield while 1;
66};
67
68=item $main 69=item $main
69 70
70This coroutine represents the main program. 71This coroutine represents the main program.
71 72
72=cut 73=cut
73 74
74$main = new Coro; 75our $main = new Coro;
75 76
76=item $current 77=item $current
77 78
78The current coroutine (the last coroutine switched to). The initial value is C<$main> (of course). 79The current coroutine (the last coroutine switched to). The initial value is C<$main> (of course).
79 80
82# maybe some other module used Coro::Specific before... 83# maybe some other module used Coro::Specific before...
83if ($current) { 84if ($current) {
84 $main->{specific} = $current->{specific}; 85 $main->{specific} = $current->{specific};
85} 86}
86 87
87$current = $main; 88our $current = $main;
89
90=item $idle
91
92The coroutine to switch to when no other coroutine is running. The default
93implementation prints "FATAL: deadlock detected" and exits.
94
95=cut
96
97# should be done using priorities :(
98our $idle = new Coro sub {
99 print STDERR "FATAL: deadlock detected\n";
100 exit(51);
101};
88 102
89# we really need priorities... 103# we really need priorities...
90my @ready = (); # the ready queue. hehe, rather broken ;) 104my @ready; # the ready queue. hehe, rather broken ;)
91 105
92# static methods. not really. 106# static methods. not really.
93 107
94=head2 STATIC METHODS 108=head2 STATIC METHODS
95 109
96Static methods are actually functions that operate on the current process only. 110Static methods are actually functions that operate on the current process only.
97 111
98=over 4 112=over 4
99 113
100=item async { ... }; 114=item async { ... } [@args...]
101 115
102Create a new asynchronous process and return it's process object 116Create a new asynchronous process and return it's process object
103(usually unused). When the sub returns the new process is automatically 117(usually unused). When the sub returns the new process is automatically
104terminated. 118terminated.
105 119
106=cut 120 # create a new coroutine that just prints its arguments
121 async {
122 print "@_\n";
123 } 1,2,3,4;
107 124
125The coderef you submit MUST NOT be a closure that refers to variables
126in an outer scope. This does NOT work. Pass arguments into it instead.
127
128=cut
129
108sub async(&) { 130sub async(&@) {
109 (new Coro $_[0])->ready; 131 my $pid = new Coro @_;
132 $pid->ready;
133 $pid;
110} 134}
111 135
112=item schedule 136=item schedule
113 137
114Calls the scheduler. Please note that the current process will not be put 138Calls the scheduler. Please note that the current process will not be put
118=cut 142=cut
119 143
120my $prev; 144my $prev;
121 145
122sub schedule { 146sub schedule {
147 # should be done using priorities :(
123 ($prev, $current) = ($current, shift @ready); 148 ($prev, $current) = ($current, shift @ready || $idle);
124 Coro::State::transfer($prev, $current); 149 Coro::State::transfer($prev, $current);
125} 150}
126 151
127=item yield 152=item yield
128 153
138 163
139=item terminate 164=item terminate
140 165
141Terminates the current process. 166Terminates the current process.
142 167
168Future versions of this function will allow result arguments.
169
143=cut 170=cut
144 171
145sub terminate { 172sub terminate {
173 $current->{_results} = [@_];
146 &schedule; 174 &schedule;
147} 175}
148 176
149=back 177=back
150 178
154 182
155These are the methods you can call on process objects. 183These are the methods you can call on process objects.
156 184
157=over 4 185=over 4
158 186
159=item new Coro \&sub; 187=item new Coro \&sub [, @args...]
160 188
161Create a new process and return it. When the sub returns the process 189Create a new process and return it. When the sub returns the process
162automatically terminates. To start the process you must first put it into 190automatically terminates. To start the process you must first put it into
163the ready queue by calling the ready method. 191the ready queue by calling the ready method.
164 192
193The coderef you submit MUST NOT be a closure that refers to variables
194in an outer scope. This does NOT work. Pass arguments into it instead.
195
165=cut 196=cut
197
198sub _newcoro {
199 terminate &{+shift};
200}
166 201
167sub new { 202sub new {
168 my $class = shift; 203 my $class = shift;
169 my $proc = $_[0];
170 bless { 204 bless {
171 _coro_state => new Coro::State ($proc ? sub { &$proc; &terminate } : $proc), 205 _coro_state => (new Coro::State $_[0] && \&_newcoro, @_),
172 }, $class; 206 }, $class;
173} 207}
174 208
175=item $process->ready 209=item $process->ready
176 210
186 220
187=cut 221=cut
188 222
1891; 2231;
190 224
225=head1 BUGS/LIMITATIONS
226
227 - could be faster, especially when the core would introduce special
228 support for coroutines (like it does for threads).
229 - there is still a memleak on coroutine termination that I could not
230 identify. Could be as small as a single SV.
231 - this module is not well-tested.
232 - if variables or arguments "disappear" (become undef) or become
233 corrupted please contact the author so he cen iron out the
234 remaining bugs.
235 - this module is not thread-safe. You must only ever use this module from
236 the same thread (this requirement might be loosened in the future to
237 allow per-thread schedulers, but Coro::Satte does not yet allow this).
238
239=head1 SEE ALSO
240
241L<Coro::Channel>, L<Coro::Cont>, L<Coro::Specific>, L<Coro::Semaphore>,
242L<Coro::Signal>, L<Coro::State>, L<Coro::Event>.
243
191=head1 AUTHOR 244=head1 AUTHOR
192 245
193 Marc Lehmann <pcg@goof.com> 246 Marc Lehmann <pcg@goof.com>
194 http://www.goof.com/pcg/marc/ 247 http://www.goof.com/pcg/marc/
195 248

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines