ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro.pm
Revision: 1.35
Committed: Mon Sep 24 00:16:30 2001 UTC (22 years, 8 months ago) by root
Branch: MAIN
Changes since 1.34: +1 -0 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.34 $VERSION = 0.5;
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.35 &schedule if $current == $_[0];
235 root 1.31 }
236    
237     =item $oldprio = $process->prio($newprio)
238    
239     Sets the priority of the process. Higher priority processes get run before
240     lower priority processes. Priorities are smalled signed integer (currently
241     -4 .. +3), that you can refer to using PRIO_xxx constants (use the import
242     tag :prio to get then):
243    
244     PRIO_MAX > PRIO_HIGH > PRIO_NORMAL > PRIO_LOW > PRIO_IDLE > PRIO_MIN
245     3 > 1 > 0 > -1 > -3 > -4
246    
247     # set priority to HIGH
248     current->prio(PRIO_HIGH);
249    
250     The idle coroutine ($Coro::idle) always has a lower priority than any
251     existing coroutine.
252    
253     Changing the priority of the current process will take effect immediately,
254     but changing the priority of processes in the ready queue (but not
255     running) will only take effect after the next schedule (of that
256     process). This is a bug that will be fixed in some future version.
257    
258     =cut
259    
260     sub prio {
261     my $old = $_[0]{prio};
262     $_[0]{prio} = $_[1] if @_ > 1;
263     $old;
264     }
265    
266     =item $newprio = $process->nice($change)
267    
268     Similar to C<prio>, but subtract the given value from the priority (i.e.
269     higher values mean lower priority, just as in unix).
270    
271     =cut
272    
273     sub nice {
274     $_[0]{prio} -= $_[1];
275 root 1.8 }
276 root 1.1
277 root 1.8 =back
278 root 1.2
279 root 1.8 =cut
280 root 1.2
281 root 1.8 1;
282 root 1.14
283 root 1.17 =head1 BUGS/LIMITATIONS
284 root 1.14
285 root 1.33 - you must make very sure that no coro is still active on global destruction.
286     very bad things might happen otherwise (usually segfaults).
287 root 1.17 - this module is not thread-safe. You must only ever use this module from
288     the same thread (this requirement might be loosened in the future to
289 root 1.20 allow per-thread schedulers, but Coro::State does not yet allow this).
290 root 1.9
291     =head1 SEE ALSO
292    
293     L<Coro::Channel>, L<Coro::Cont>, L<Coro::Specific>, L<Coro::Semaphore>,
294 root 1.25 L<Coro::Signal>, L<Coro::State>, L<Coro::Event>, L<Coro::RWLock>,
295 root 1.26 L<Coro::Handle>, L<Coro::Socket>.
296 root 1.1
297     =head1 AUTHOR
298    
299     Marc Lehmann <pcg@goof.com>
300     http://www.goof.com/pcg/marc/
301    
302     =cut
303