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