ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro.pm
Revision: 1.12
Committed: Sun Jul 15 15:58:16 2001 UTC (22 years, 10 months ago) by root
Branch: MAIN
Changes since 1.11: +2 -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.12 $VERSION = 0.05;
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.12 local @_;
135 root 1.9 # should be done using priorities :(
136     ($prev, $current) = ($current, shift @ready || $idle);
137 root 1.8 Coro::State::transfer($prev, $current);
138 root 1.1 }
139    
140 root 1.8 =item yield
141 root 1.1
142 root 1.8 Yield to other processes. This function puts the current process into the
143     ready queue and calls C<schedule>.
144 root 1.7
145 root 1.8 =cut
146    
147     sub yield {
148     $current->ready;
149     &schedule;
150     }
151 root 1.7
152 root 1.8 =item terminate
153 root 1.7
154 root 1.8 Terminates the current process.
155 root 1.1
156     =cut
157    
158 root 1.8 sub terminate {
159     &schedule;
160 root 1.1 }
161 root 1.6
162 root 1.8 =back
163    
164     # dynamic methods
165    
166     =head2 PROCESS METHODS
167    
168     These are the methods you can call on process objects.
169 root 1.6
170 root 1.8 =over 4
171    
172     =item new Coro \&sub;
173    
174     Create a new process and return it. When the sub returns the process
175     automatically terminates. To start the process you must first put it into
176     the ready queue by calling the ready method.
177 root 1.6
178     =cut
179    
180 root 1.8 sub new {
181     my $class = shift;
182     my $proc = $_[0];
183     bless {
184     _coro_state => new Coro::State ($proc ? sub { &$proc; &terminate } : $proc),
185     }, $class;
186     }
187 root 1.6
188 root 1.8 =item $process->ready
189 root 1.1
190 root 1.8 Put the current process into the ready queue.
191 root 1.1
192 root 1.8 =cut
193 root 1.1
194 root 1.8 sub ready {
195     push @ready, $_[0];
196     }
197 root 1.1
198 root 1.8 =back
199 root 1.2
200 root 1.8 =cut
201 root 1.2
202 root 1.8 1;
203 root 1.9
204     =head1 SEE ALSO
205    
206     L<Coro::Channel>, L<Coro::Cont>, L<Coro::Specific>, L<Coro::Semaphore>,
207 root 1.10 L<Coro::Signal>, L<Coro::State>, L<Coro::Event>.
208 root 1.1
209     =head1 AUTHOR
210    
211     Marc Lehmann <pcg@goof.com>
212     http://www.goof.com/pcg/marc/
213    
214     =cut
215