ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro.pm
Revision: 1.25
Committed: Wed Jul 25 21:12:57 2001 UTC (22 years, 10 months ago) by root
Branch: MAIN
Changes since 1.24: +2 -1 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 cede;
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 + 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
33 =cut
34
35 package Coro;
36
37 use Coro::State;
38
39 use base Exporter;
40
41 $VERSION = 0.12;
42
43 @EXPORT = qw(async cede schedule terminate current);
44 @EXPORT_OK = qw($current);
45
46 {
47 my @async;
48
49 # this way of handling attributes simply is NOT scalable ;()
50 sub import {
51 Coro->export_to_level(1, @_);
52 my $old = *{(caller)[0]."::MODIFY_CODE_ATTRIBUTES"}{CODE};
53 *{(caller)[0]."::MODIFY_CODE_ATTRIBUTES"} = sub {
54 my ($package, $ref) = (shift, shift);
55 my @attrs;
56 for (@_) {
57 if ($_ eq "Coro") {
58 push @async, $ref;
59 } else {
60 push @attrs, $_;
61 }
62 }
63 return $old ? $old->($package, $ref, @attrs) : @attrs;
64 };
65 }
66
67 sub INIT {
68 &async(pop @async) while @async;
69 }
70 }
71
72 =item $main
73
74 This coroutine represents the main program.
75
76 =cut
77
78 our $main = new Coro;
79
80 =item $current (or as function: current)
81
82 The current coroutine (the last coroutine switched to). The initial value is C<$main> (of course).
83
84 =cut
85
86 # maybe some other module used Coro::Specific before...
87 if ($current) {
88 $main->{specific} = $current->{specific};
89 }
90
91 our $current = $main;
92
93 sub current() { $current }
94
95 =item $idle
96
97 The coroutine to switch to when no other coroutine is running. The default
98 implementation prints "FATAL: deadlock detected" and exits.
99
100 =cut
101
102 # should be done using priorities :(
103 our $idle = new Coro sub {
104 print STDERR "FATAL: deadlock detected\n";
105 exit(51);
106 };
107
108 # this coroutine is necessary because a coroutine
109 # cannot destroy itself.
110 my @destroy;
111 my $manager = new Coro sub {
112 while() {
113 delete ((pop @destroy)->{_coro_state}) while @destroy;
114 &schedule;
115 }
116 };
117
118 # we really need priorities...
119 my @ready; # the ready queue. hehe, rather broken ;)
120
121 # static methods. not really.
122
123 =head2 STATIC METHODS
124
125 Static methods are actually functions that operate on the current process only.
126
127 =over 4
128
129 =item async { ... } [@args...]
130
131 Create a new asynchronous process and return it's process object
132 (usually unused). When the sub returns the new process is automatically
133 terminated.
134
135 # create a new coroutine that just prints its arguments
136 async {
137 print "@_\n";
138 } 1,2,3,4;
139
140 The coderef you submit MUST NOT be a closure that refers to variables
141 in an outer scope. This does NOT work. Pass arguments into it instead.
142
143 =cut
144
145 sub async(&@) {
146 my $pid = new Coro @_;
147 $manager->ready; # this ensures that the stack is cloned from the manager
148 $pid->ready;
149 $pid;
150 }
151
152 =item schedule
153
154 Calls the scheduler. Please note that the current process will not be put
155 into the ready queue, so calling this function usually means you will
156 never be called again.
157
158 =cut
159
160 my $prev;
161
162 sub schedule {
163 # should be done using priorities :(
164 ($prev, $current) = ($current, shift @ready || $idle);
165 Coro::State::transfer($prev, $current);
166 }
167
168 =item cede
169
170 "Cede" to other processes. This function puts the current process into the
171 ready queue and calls C<schedule>, which has the effect of giving up the
172 current "timeslice" to other coroutines of the same or higher priority.
173
174 =cut
175
176 sub cede {
177 $current->ready;
178 &schedule;
179 }
180
181 =item terminate
182
183 Terminates the current process.
184
185 Future versions of this function will allow result arguments.
186
187 =cut
188
189 sub terminate {
190 push @destroy, $current;
191 $manager->ready;
192 &schedule;
193 # NORETURN
194 }
195
196 =back
197
198 # dynamic methods
199
200 =head2 PROCESS METHODS
201
202 These are the methods you can call on process objects.
203
204 =over 4
205
206 =item new Coro \&sub [, @args...]
207
208 Create a new process and return it. When the sub returns the process
209 automatically terminates. To start the process you must first put it into
210 the ready queue by calling the ready method.
211
212 The coderef you submit MUST NOT be a closure that refers to variables
213 in an outer scope. This does NOT work. Pass arguments into it instead.
214
215 =cut
216
217 sub _newcoro {
218 terminate &{+shift};
219 }
220
221 sub new {
222 my $class = shift;
223 bless {
224 _coro_state => (new Coro::State $_[0] && \&_newcoro, @_),
225 }, $class;
226 }
227
228 =item $process->ready
229
230 Put the current process into the ready queue.
231
232 =cut
233
234 sub ready {
235 push @ready, $_[0];
236 }
237
238 =back
239
240 =cut
241
242 1;
243
244 =head1 BUGS/LIMITATIONS
245
246 - could be faster, especially when the core would introduce special
247 support for coroutines (like it does for threads).
248 - there is still a memleak on coroutine termination that I could not
249 identify. Could be as small as a single SV.
250 - this module is not well-tested.
251 - if variables or arguments "disappear" (become undef) or become
252 corrupted please contact the author so he cen iron out the
253 remaining bugs.
254 - this module is not thread-safe. You must only ever use this module from
255 the same thread (this requirement might be loosened in the future to
256 allow per-thread schedulers, but Coro::State does not yet allow this).
257
258 =head1 SEE ALSO
259
260 L<Coro::Channel>, L<Coro::Cont>, L<Coro::Specific>, L<Coro::Semaphore>,
261 L<Coro::Signal>, L<Coro::State>, L<Coro::Event>, L<Coro::RWLock>,
262 L<Coro::L<Coro::Handle>, L<Coro::Socket>.
263
264 =head1 AUTHOR
265
266 Marc Lehmann <pcg@goof.com>
267 http://www.goof.com/pcg/marc/
268
269 =cut
270