ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro.pm
Revision: 1.32
Committed: Sun Sep 2 01:03:53 2001 UTC (22 years, 9 months ago) by root
Branch: MAIN
Changes since 1.31: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 =head1 NAME
2    
3 root 1.8 Coro - coroutine process abstraction
4 root 1.1
5     =head1 SYNOPSIS
6    
7     use Coro;
8    
9 root 1.8 async {
10     # some asynchronous thread of execution
11 root 1.2 };
12    
13 root 1.8 # alternatively create an async process like this:
14 root 1.6
15 root 1.8 sub some_func : Coro {
16     # some more async code
17     }
18    
19 root 1.22 cede;
20 root 1.2
21 root 1.1 =head1 DESCRIPTION
22    
23 root 1.14 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 root 1.20 In this module, coroutines are defined as "callchain + lexical variables
29 root 1.23 + @_ + $_ + $@ + $^W + C stack), that is, a coroutine has it's own
30     callchain, it's own set of lexicals and it's own set of perl's most
31     important global variables.
32 root 1.22
33 root 1.8 =cut
34    
35     package Coro;
36    
37     use Coro::State;
38    
39     use base Exporter;
40    
41 root 1.32 $VERSION = 0.49;
42 root 1.8
43 root 1.22 @EXPORT = qw(async cede schedule terminate current);
44 root 1.31 %EXPORT_TAGS = (
45     prio => [qw(PRIO_MAX PRIO_HIGH PRIO_NORMAL PRIO_LOW PRIO_IDLE PRIO_MIN)],
46     );
47     @EXPORT_OK = @{$EXPORT_TAGS{prio}};
48 root 1.8
49     {
50     my @async;
51 root 1.26 my $init;
52 root 1.8
53     # this way of handling attributes simply is NOT scalable ;()
54     sub import {
55     Coro->export_to_level(1, @_);
56     my $old = *{(caller)[0]."::MODIFY_CODE_ATTRIBUTES"}{CODE};
57     *{(caller)[0]."::MODIFY_CODE_ATTRIBUTES"} = sub {
58     my ($package, $ref) = (shift, shift);
59     my @attrs;
60     for (@_) {
61     if ($_ eq "Coro") {
62     push @async, $ref;
63 root 1.26 unless ($init++) {
64     eval q{
65     sub INIT {
66     &async(pop @async) while @async;
67     }
68     };
69     }
70 root 1.8 } else {
71 root 1.17 push @attrs, $_;
72 root 1.8 }
73     }
74 root 1.17 return $old ? $old->($package, $ref, @attrs) : @attrs;
75 root 1.8 };
76     }
77    
78     }
79    
80     =item $main
81 root 1.2
82 root 1.8 This coroutine represents the main program.
83 root 1.1
84     =cut
85    
86 root 1.9 our $main = new Coro;
87 root 1.8
88 root 1.19 =item $current (or as function: current)
89 root 1.1
90 root 1.8 The current coroutine (the last coroutine switched to). The initial value is C<$main> (of course).
91 root 1.1
92 root 1.8 =cut
93    
94     # maybe some other module used Coro::Specific before...
95     if ($current) {
96     $main->{specific} = $current->{specific};
97 root 1.1 }
98    
99 root 1.9 our $current = $main;
100 root 1.19
101     sub current() { $current }
102 root 1.9
103     =item $idle
104    
105     The coroutine to switch to when no other coroutine is running. The default
106     implementation prints "FATAL: deadlock detected" and exits.
107    
108     =cut
109    
110     # should be done using priorities :(
111     our $idle = new Coro sub {
112     print STDERR "FATAL: deadlock detected\n";
113     exit(51);
114     };
115 root 1.8
116 root 1.24 # this coroutine is necessary because a coroutine
117     # cannot destroy itself.
118     my @destroy;
119     my $manager = new Coro sub {
120     while() {
121     delete ((pop @destroy)->{_coro_state}) while @destroy;
122     &schedule;
123     }
124     };
125    
126 root 1.8 # static methods. not really.
127    
128     =head2 STATIC METHODS
129    
130     Static methods are actually functions that operate on the current process only.
131    
132     =over 4
133    
134 root 1.13 =item async { ... } [@args...]
135 root 1.8
136     Create a new asynchronous process and return it's process object
137     (usually unused). When the sub returns the new process is automatically
138     terminated.
139    
140 root 1.13 # create a new coroutine that just prints its arguments
141     async {
142     print "@_\n";
143     } 1,2,3,4;
144    
145     The coderef you submit MUST NOT be a closure that refers to variables
146     in an outer scope. This does NOT work. Pass arguments into it instead.
147    
148 root 1.8 =cut
149    
150 root 1.13 sub async(&@) {
151     my $pid = new Coro @_;
152 root 1.24 $manager->ready; # this ensures that the stack is cloned from the manager
153 root 1.11 $pid->ready;
154     $pid;
155 root 1.8 }
156 root 1.1
157 root 1.8 =item schedule
158 root 1.6
159 root 1.8 Calls the scheduler. Please note that the current process will not be put
160     into the ready queue, so calling this function usually means you will
161     never be called again.
162 root 1.1
163     =cut
164    
165 root 1.22 =item cede
166 root 1.1
167 root 1.22 "Cede" to other processes. This function puts the current process into the
168     ready queue and calls C<schedule>, which has the effect of giving up the
169     current "timeslice" to other coroutines of the same or higher priority.
170 root 1.7
171 root 1.8 =cut
172    
173     =item terminate
174 root 1.7
175 root 1.8 Terminates the current process.
176 root 1.1
177 root 1.13 Future versions of this function will allow result arguments.
178    
179 root 1.1 =cut
180    
181 root 1.8 sub terminate {
182 root 1.28 $current->cancel;
183 root 1.23 &schedule;
184 root 1.28 die; # NORETURN
185 root 1.1 }
186 root 1.6
187 root 1.8 =back
188    
189     # dynamic methods
190    
191     =head2 PROCESS METHODS
192    
193     These are the methods you can call on process objects.
194 root 1.6
195 root 1.8 =over 4
196    
197 root 1.13 =item new Coro \&sub [, @args...]
198 root 1.8
199     Create a new process and return it. When the sub returns the process
200     automatically terminates. To start the process you must first put it into
201     the ready queue by calling the ready method.
202 root 1.6
203 root 1.13 The coderef you submit MUST NOT be a closure that refers to variables
204     in an outer scope. This does NOT work. Pass arguments into it instead.
205    
206 root 1.6 =cut
207    
208 root 1.13 sub _newcoro {
209     terminate &{+shift};
210     }
211    
212 root 1.8 sub new {
213     my $class = shift;
214     bless {
215 root 1.13 _coro_state => (new Coro::State $_[0] && \&_newcoro, @_),
216 root 1.8 }, $class;
217     }
218 root 1.6
219 root 1.8 =item $process->ready
220 root 1.1
221 root 1.8 Put the current process into the ready queue.
222 root 1.1
223 root 1.8 =cut
224 root 1.28
225     =item $process->cancel
226    
227     Like C<terminate>, but terminates the specified process instead.
228    
229     =cut
230    
231     sub cancel {
232     push @destroy, $_[0];
233     $manager->ready;
234 root 1.31 }
235    
236     =item $oldprio = $process->prio($newprio)
237    
238     Sets the priority of the process. Higher priority processes get run before
239     lower priority processes. Priorities are smalled signed integer (currently
240     -4 .. +3), that you can refer to using PRIO_xxx constants (use the import
241     tag :prio to get then):
242    
243     PRIO_MAX > PRIO_HIGH > PRIO_NORMAL > PRIO_LOW > PRIO_IDLE > PRIO_MIN
244     3 > 1 > 0 > -1 > -3 > -4
245    
246     # set priority to HIGH
247     current->prio(PRIO_HIGH);
248    
249     The idle coroutine ($Coro::idle) always has a lower priority than any
250     existing coroutine.
251    
252     Changing the priority of the current process will take effect immediately,
253     but changing the priority of processes in the ready queue (but not
254     running) will only take effect after the next schedule (of that
255     process). This is a bug that will be fixed in some future version.
256    
257     =cut
258    
259     sub prio {
260     my $old = $_[0]{prio};
261     $_[0]{prio} = $_[1] if @_ > 1;
262     $old;
263     }
264    
265     =item $newprio = $process->nice($change)
266    
267     Similar to C<prio>, but subtract the given value from the priority (i.e.
268     higher values mean lower priority, just as in unix).
269    
270     =cut
271    
272     sub nice {
273     $_[0]{prio} -= $_[1];
274 root 1.8 }
275 root 1.1
276 root 1.8 =back
277 root 1.2
278 root 1.8 =cut
279 root 1.2
280 root 1.8 1;
281 root 1.14
282 root 1.17 =head1 BUGS/LIMITATIONS
283 root 1.14
284     - could be faster, especially when the core would introduce special
285     support for coroutines (like it does for threads).
286     - there is still a memleak on coroutine termination that I could not
287     identify. Could be as small as a single SV.
288     - this module is not well-tested.
289 root 1.17 - if variables or arguments "disappear" (become undef) or become
290     corrupted please contact the author so he cen iron out the
291     remaining bugs.
292     - this module is not thread-safe. You must only ever use this module from
293     the same thread (this requirement might be loosened in the future to
294 root 1.20 allow per-thread schedulers, but Coro::State does not yet allow this).
295 root 1.9
296     =head1 SEE ALSO
297    
298     L<Coro::Channel>, L<Coro::Cont>, L<Coro::Specific>, L<Coro::Semaphore>,
299 root 1.25 L<Coro::Signal>, L<Coro::State>, L<Coro::Event>, L<Coro::RWLock>,
300 root 1.26 L<Coro::Handle>, L<Coro::Socket>.
301 root 1.1
302     =head1 AUTHOR
303    
304     Marc Lehmann <pcg@goof.com>
305     http://www.goof.com/pcg/marc/
306    
307     =cut
308