ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro.pm
Revision: 1.13
Committed: Tue Jul 17 00:24:14 2001 UTC (22 years, 10 months ago) by root
Branch: MAIN
Changes since 1.12: +26 -9 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     yield;
20 root 1.2
21 root 1.1 =head1 DESCRIPTION
22    
23 root 1.8 =cut
24    
25     package Coro;
26    
27     use Coro::State;
28    
29     use base Exporter;
30    
31 root 1.12 $VERSION = 0.05;
32 root 1.8
33 root 1.13 @EXPORT = qw(async yield schedule terminate);
34 root 1.8 @EXPORT_OK = qw($current);
35    
36     {
37     use subs 'async';
38    
39     my @async;
40    
41     # this way of handling attributes simply is NOT scalable ;()
42     sub import {
43     Coro->export_to_level(1, @_);
44     my $old = *{(caller)[0]."::MODIFY_CODE_ATTRIBUTES"}{CODE};
45     *{(caller)[0]."::MODIFY_CODE_ATTRIBUTES"} = sub {
46     my ($package, $ref) = (shift, shift);
47     my @attrs;
48     for (@_) {
49     if ($_ eq "Coro") {
50     push @async, $ref;
51     } else {
52     push @attrs, @_;
53     }
54     }
55     return $old ? $old->($package, $name, @attrs) : @attrs;
56     };
57     }
58    
59     sub INIT {
60     async pop @async while @async;
61     }
62     }
63    
64     =item $main
65 root 1.2
66 root 1.8 This coroutine represents the main program.
67 root 1.1
68     =cut
69    
70 root 1.9 our $main = new Coro;
71 root 1.8
72     =item $current
73 root 1.1
74 root 1.8 The current coroutine (the last coroutine switched to). The initial value is C<$main> (of course).
75 root 1.1
76 root 1.8 =cut
77    
78     # maybe some other module used Coro::Specific before...
79     if ($current) {
80     $main->{specific} = $current->{specific};
81 root 1.1 }
82    
83 root 1.9 our $current = $main;
84    
85     =item $idle
86    
87     The coroutine to switch to when no other coroutine is running. The default
88     implementation prints "FATAL: deadlock detected" and exits.
89    
90     =cut
91    
92     # should be done using priorities :(
93     our $idle = new Coro sub {
94     print STDERR "FATAL: deadlock detected\n";
95     exit(51);
96     };
97 root 1.8
98     # we really need priorities...
99 root 1.13 ## my @ready; #d#
100     our @ready = (); # the ready queue. hehe, rather broken ;)
101 root 1.8
102     # static methods. not really.
103    
104     =head2 STATIC METHODS
105    
106     Static methods are actually functions that operate on the current process only.
107    
108     =over 4
109    
110 root 1.13 =item async { ... } [@args...]
111 root 1.8
112     Create a new asynchronous process and return it's process object
113     (usually unused). When the sub returns the new process is automatically
114     terminated.
115    
116 root 1.13 # create a new coroutine that just prints its arguments
117     async {
118     print "@_\n";
119     } 1,2,3,4;
120    
121     The coderef you submit MUST NOT be a closure that refers to variables
122     in an outer scope. This does NOT work. Pass arguments into it instead.
123    
124 root 1.8 =cut
125    
126 root 1.13 sub async(&@) {
127     my $pid = new Coro @_;
128 root 1.11 $pid->ready;
129     $pid;
130 root 1.8 }
131 root 1.1
132 root 1.8 =item schedule
133 root 1.6
134 root 1.8 Calls the scheduler. Please note that the current process will not be put
135     into the ready queue, so calling this function usually means you will
136     never be called again.
137 root 1.1
138     =cut
139    
140 root 1.8 my $prev;
141    
142     sub schedule {
143 root 1.9 # should be done using priorities :(
144     ($prev, $current) = ($current, shift @ready || $idle);
145 root 1.8 Coro::State::transfer($prev, $current);
146 root 1.1 }
147    
148 root 1.8 =item yield
149 root 1.1
150 root 1.8 Yield to other processes. This function puts the current process into the
151     ready queue and calls C<schedule>.
152 root 1.7
153 root 1.8 =cut
154    
155     sub yield {
156     $current->ready;
157     &schedule;
158     }
159 root 1.7
160 root 1.8 =item terminate
161 root 1.7
162 root 1.8 Terminates the current process.
163 root 1.1
164 root 1.13 Future versions of this function will allow result arguments.
165    
166 root 1.1 =cut
167    
168 root 1.8 sub terminate {
169 root 1.13 $current->{_results} = [@_];
170 root 1.8 &schedule;
171 root 1.1 }
172 root 1.6
173 root 1.8 =back
174    
175     # dynamic methods
176    
177     =head2 PROCESS METHODS
178    
179     These are the methods you can call on process objects.
180 root 1.6
181 root 1.8 =over 4
182    
183 root 1.13 =item new Coro \&sub [, @args...]
184 root 1.8
185     Create a new process and return it. When the sub returns the process
186     automatically terminates. To start the process you must first put it into
187     the ready queue by calling the ready method.
188 root 1.6
189 root 1.13 The coderef you submit MUST NOT be a closure that refers to variables
190     in an outer scope. This does NOT work. Pass arguments into it instead.
191    
192 root 1.6 =cut
193    
194 root 1.13 sub _newcoro {
195     terminate &{+shift};
196     }
197    
198 root 1.8 sub new {
199     my $class = shift;
200     bless {
201 root 1.13 _coro_state => (new Coro::State $_[0] && \&_newcoro, @_),
202 root 1.8 }, $class;
203     }
204 root 1.6
205 root 1.8 =item $process->ready
206 root 1.1
207 root 1.8 Put the current process into the ready queue.
208 root 1.1
209 root 1.8 =cut
210 root 1.1
211 root 1.8 sub ready {
212     push @ready, $_[0];
213     }
214 root 1.1
215 root 1.8 =back
216 root 1.2
217 root 1.8 =cut
218 root 1.2
219 root 1.8 1;
220 root 1.9
221     =head1 SEE ALSO
222    
223     L<Coro::Channel>, L<Coro::Cont>, L<Coro::Specific>, L<Coro::Semaphore>,
224 root 1.10 L<Coro::Signal>, L<Coro::State>, L<Coro::Event>.
225 root 1.1
226     =head1 AUTHOR
227    
228     Marc Lehmann <pcg@goof.com>
229     http://www.goof.com/pcg/marc/
230    
231     =cut
232