ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro.pm
Revision: 1.11
Committed: Sun Jul 15 03:24:18 2001 UTC (22 years, 11 months ago) by root
Branch: MAIN
Changes since 1.10: +3 -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     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.9 $VERSION = 0.04;
32 root 1.8
33     @EXPORT = qw(async yield schedule);
34     @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     my @ready = (); # the ready queue. hehe, rather broken ;)
100    
101     # static methods. not really.
102    
103     =head2 STATIC METHODS
104    
105     Static methods are actually functions that operate on the current process only.
106    
107     =over 4
108    
109     =item async { ... };
110    
111     Create a new asynchronous process and return it's process object
112     (usually unused). When the sub returns the new process is automatically
113     terminated.
114    
115     =cut
116    
117     sub async(&) {
118 root 1.11 my $pid = new Coro $_[0];
119     $pid->ready;
120     $pid;
121 root 1.8 }
122 root 1.1
123 root 1.8 =item schedule
124 root 1.6
125 root 1.8 Calls the scheduler. Please note that the current process will not be put
126     into the ready queue, so calling this function usually means you will
127     never be called again.
128 root 1.1
129     =cut
130    
131 root 1.8 my $prev;
132    
133     sub schedule {
134 root 1.9 # should be done using priorities :(
135     ($prev, $current) = ($current, shift @ready || $idle);
136 root 1.8 Coro::State::transfer($prev, $current);
137 root 1.1 }
138    
139 root 1.8 =item yield
140 root 1.1
141 root 1.8 Yield to other processes. This function puts the current process into the
142     ready queue and calls C<schedule>.
143 root 1.7
144 root 1.8 =cut
145    
146     sub yield {
147     $current->ready;
148     &schedule;
149     }
150 root 1.7
151 root 1.8 =item terminate
152 root 1.7
153 root 1.8 Terminates the current process.
154 root 1.1
155     =cut
156    
157 root 1.8 sub terminate {
158     &schedule;
159 root 1.1 }
160 root 1.6
161 root 1.8 =back
162    
163     # dynamic methods
164    
165     =head2 PROCESS METHODS
166    
167     These are the methods you can call on process objects.
168 root 1.6
169 root 1.8 =over 4
170    
171     =item new Coro \&sub;
172    
173     Create a new process and return it. When the sub returns the process
174     automatically terminates. To start the process you must first put it into
175     the ready queue by calling the ready method.
176 root 1.6
177     =cut
178    
179 root 1.8 sub new {
180     my $class = shift;
181     my $proc = $_[0];
182     bless {
183     _coro_state => new Coro::State ($proc ? sub { &$proc; &terminate } : $proc),
184     }, $class;
185     }
186 root 1.6
187 root 1.8 =item $process->ready
188 root 1.1
189 root 1.8 Put the current process into the ready queue.
190 root 1.1
191 root 1.8 =cut
192 root 1.1
193 root 1.8 sub ready {
194     push @ready, $_[0];
195     }
196 root 1.1
197 root 1.8 =back
198 root 1.2
199 root 1.8 =cut
200 root 1.2
201 root 1.8 1;
202 root 1.9
203     =head1 SEE ALSO
204    
205     L<Coro::Channel>, L<Coro::Cont>, L<Coro::Specific>, L<Coro::Semaphore>,
206 root 1.10 L<Coro::Signal>, L<Coro::State>, L<Coro::Event>.
207 root 1.1
208     =head1 AUTHOR
209    
210     Marc Lehmann <pcg@goof.com>
211     http://www.goof.com/pcg/marc/
212    
213     =cut
214