ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro.pm
Revision: 1.21
Committed: Sun Jul 22 03:24:10 2001 UTC (22 years, 10 months ago) by root
Branch: MAIN
Changes since 1.20: +7 -0 lines
Log Message:
*** empty log message ***

File Contents

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