ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro.pm
Revision: 1.37
Committed: Mon Sep 24 02:25:44 2001 UTC (22 years, 8 months ago) by root
Branch: MAIN
Changes since 1.36: +6 -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 root 1.36 no warnings qw(uninitialized);
38    
39 root 1.8 use Coro::State;
40    
41     use base Exporter;
42    
43 root 1.34 $VERSION = 0.5;
44 root 1.8
45 root 1.22 @EXPORT = qw(async cede schedule terminate current);
46 root 1.31 %EXPORT_TAGS = (
47     prio => [qw(PRIO_MAX PRIO_HIGH PRIO_NORMAL PRIO_LOW PRIO_IDLE PRIO_MIN)],
48     );
49     @EXPORT_OK = @{$EXPORT_TAGS{prio}};
50 root 1.8
51     {
52     my @async;
53 root 1.26 my $init;
54 root 1.8
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 root 1.26 unless ($init++) {
66     eval q{
67     sub INIT {
68     &async(pop @async) while @async;
69     }
70     };
71     }
72 root 1.8 } else {
73 root 1.17 push @attrs, $_;
74 root 1.8 }
75     }
76 root 1.17 return $old ? $old->($package, $ref, @attrs) : @attrs;
77 root 1.8 };
78     }
79    
80     }
81    
82     =item $main
83 root 1.2
84 root 1.8 This coroutine represents the main program.
85 root 1.1
86     =cut
87    
88 root 1.9 our $main = new Coro;
89 root 1.8
90 root 1.19 =item $current (or as function: current)
91 root 1.1
92 root 1.8 The current coroutine (the last coroutine switched to). The initial value is C<$main> (of course).
93 root 1.1
94 root 1.8 =cut
95    
96     # maybe some other module used Coro::Specific before...
97     if ($current) {
98     $main->{specific} = $current->{specific};
99 root 1.1 }
100    
101 root 1.9 our $current = $main;
102 root 1.19
103     sub current() { $current }
104 root 1.9
105     =item $idle
106    
107     The coroutine to switch to when no other coroutine is running. The default
108     implementation prints "FATAL: deadlock detected" and exits.
109    
110     =cut
111    
112     # should be done using priorities :(
113     our $idle = new Coro sub {
114     print STDERR "FATAL: deadlock detected\n";
115     exit(51);
116     };
117 root 1.8
118 root 1.24 # this coroutine is necessary because a coroutine
119     # cannot destroy itself.
120     my @destroy;
121     my $manager = new Coro sub {
122     while() {
123 root 1.37 # by overwriting the state object with the manager we destroy it
124     # while still being able to schedule this coroutine (in case it has
125     # been readied multiple times. this is harmless since the manager
126     # can be called as many times as neccessary and will always
127     # remove itself from the runqueue
128     (pop @destroy)->{_coro_state} = $manager->{_coro_state} while @destroy;
129 root 1.24 &schedule;
130     }
131     };
132    
133 root 1.8 # static methods. not really.
134    
135     =head2 STATIC METHODS
136    
137     Static methods are actually functions that operate on the current process only.
138    
139     =over 4
140    
141 root 1.13 =item async { ... } [@args...]
142 root 1.8
143     Create a new asynchronous process and return it's process object
144     (usually unused). When the sub returns the new process is automatically
145     terminated.
146    
147 root 1.13 # create a new coroutine that just prints its arguments
148     async {
149     print "@_\n";
150     } 1,2,3,4;
151    
152     The coderef you submit MUST NOT be a closure that refers to variables
153     in an outer scope. This does NOT work. Pass arguments into it instead.
154    
155 root 1.8 =cut
156    
157 root 1.13 sub async(&@) {
158     my $pid = new Coro @_;
159 root 1.24 $manager->ready; # this ensures that the stack is cloned from the manager
160 root 1.11 $pid->ready;
161     $pid;
162 root 1.8 }
163 root 1.1
164 root 1.8 =item schedule
165 root 1.6
166 root 1.8 Calls the scheduler. Please note that the current process will not be put
167     into the ready queue, so calling this function usually means you will
168     never be called again.
169 root 1.1
170     =cut
171    
172 root 1.22 =item cede
173 root 1.1
174 root 1.22 "Cede" to other processes. This function puts the current process into the
175     ready queue and calls C<schedule>, which has the effect of giving up the
176     current "timeslice" to other coroutines of the same or higher priority.
177 root 1.7
178 root 1.8 =cut
179    
180     =item terminate
181 root 1.7
182 root 1.8 Terminates the current process.
183 root 1.1
184 root 1.13 Future versions of this function will allow result arguments.
185    
186 root 1.1 =cut
187    
188 root 1.8 sub terminate {
189 root 1.28 $current->cancel;
190 root 1.23 &schedule;
191 root 1.28 die; # NORETURN
192 root 1.1 }
193 root 1.6
194 root 1.8 =back
195    
196     # dynamic methods
197    
198     =head2 PROCESS METHODS
199    
200     These are the methods you can call on process objects.
201 root 1.6
202 root 1.8 =over 4
203    
204 root 1.13 =item new Coro \&sub [, @args...]
205 root 1.8
206     Create a new process and return it. When the sub returns the process
207     automatically terminates. To start the process you must first put it into
208     the ready queue by calling the ready method.
209 root 1.6
210 root 1.13 The coderef you submit MUST NOT be a closure that refers to variables
211     in an outer scope. This does NOT work. Pass arguments into it instead.
212    
213 root 1.6 =cut
214    
215 root 1.13 sub _newcoro {
216     terminate &{+shift};
217     }
218    
219 root 1.8 sub new {
220     my $class = shift;
221     bless {
222 root 1.13 _coro_state => (new Coro::State $_[0] && \&_newcoro, @_),
223 root 1.8 }, $class;
224     }
225 root 1.6
226 root 1.8 =item $process->ready
227 root 1.1
228 root 1.8 Put the current process into the ready queue.
229 root 1.1
230 root 1.8 =cut
231 root 1.28
232     =item $process->cancel
233    
234     Like C<terminate>, but terminates the specified process instead.
235    
236     =cut
237    
238     sub cancel {
239     push @destroy, $_[0];
240     $manager->ready;
241 root 1.35 &schedule if $current == $_[0];
242 root 1.31 }
243    
244     =item $oldprio = $process->prio($newprio)
245    
246     Sets the priority of the process. Higher priority processes get run before
247     lower priority processes. Priorities are smalled signed integer (currently
248     -4 .. +3), that you can refer to using PRIO_xxx constants (use the import
249     tag :prio to get then):
250    
251     PRIO_MAX > PRIO_HIGH > PRIO_NORMAL > PRIO_LOW > PRIO_IDLE > PRIO_MIN
252     3 > 1 > 0 > -1 > -3 > -4
253    
254     # set priority to HIGH
255     current->prio(PRIO_HIGH);
256    
257     The idle coroutine ($Coro::idle) always has a lower priority than any
258     existing coroutine.
259    
260     Changing the priority of the current process will take effect immediately,
261     but changing the priority of processes in the ready queue (but not
262     running) will only take effect after the next schedule (of that
263     process). This is a bug that will be fixed in some future version.
264    
265     =cut
266    
267     sub prio {
268     my $old = $_[0]{prio};
269     $_[0]{prio} = $_[1] if @_ > 1;
270     $old;
271     }
272    
273     =item $newprio = $process->nice($change)
274    
275     Similar to C<prio>, but subtract the given value from the priority (i.e.
276     higher values mean lower priority, just as in unix).
277    
278     =cut
279    
280     sub nice {
281     $_[0]{prio} -= $_[1];
282 root 1.8 }
283 root 1.1
284 root 1.8 =back
285 root 1.2
286 root 1.8 =cut
287 root 1.2
288 root 1.8 1;
289 root 1.14
290 root 1.17 =head1 BUGS/LIMITATIONS
291 root 1.14
292 root 1.33 - you must make very sure that no coro is still active on global destruction.
293     very bad things might happen otherwise (usually segfaults).
294 root 1.17 - this module is not thread-safe. You must only ever use this module from
295     the same thread (this requirement might be loosened in the future to
296 root 1.20 allow per-thread schedulers, but Coro::State does not yet allow this).
297 root 1.9
298     =head1 SEE ALSO
299    
300     L<Coro::Channel>, L<Coro::Cont>, L<Coro::Specific>, L<Coro::Semaphore>,
301 root 1.25 L<Coro::Signal>, L<Coro::State>, L<Coro::Event>, L<Coro::RWLock>,
302 root 1.26 L<Coro::Handle>, L<Coro::Socket>.
303 root 1.1
304     =head1 AUTHOR
305    
306     Marc Lehmann <pcg@goof.com>
307     http://www.goof.com/pcg/marc/
308    
309     =cut
310