ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro.pm
Revision: 1.7
Committed: Fri Jul 13 13:05:38 2001 UTC (22 years, 11 months ago) by root
Branch: MAIN
Changes since 1.6: +19 -3 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 =head1 NAME
2    
3 root 1.6 Coro - create and manage simple coroutines
4 root 1.1
5     =head1 SYNOPSIS
6    
7     use Coro;
8    
9 root 1.2 $new = new Coro sub {
10     print "in coroutine, switching back\n";
11 root 1.6 $new->transfer($main);
12 root 1.2 print "in coroutine again, switching back\n";
13 root 1.6 $new->transfer($main);
14 root 1.2 };
15    
16 root 1.6 $main = new Coro;
17    
18 root 1.2 print "in main, switching to coroutine\n";
19 root 1.6 $main->transfer($new);
20 root 1.2 print "back in main, switch to coroutine again\n";
21 root 1.6 $main->transfer($new);
22 root 1.2 print "back in main\n";
23    
24 root 1.1 =head1 DESCRIPTION
25    
26 root 1.2 This module implements coroutines. Coroutines, similar to continuations,
27     allow you to run more than one "thread of execution" in parallel. Unlike
28     threads this, only voluntary switching is used so locking problems are
29     greatly reduced.
30    
31     Although this is the "main" module of the Coro family it provides only
32     low-level functionality. See L<Coro::Process> and related modules for a
33     more useful process abstraction including scheduling.
34    
35 root 1.1 =over 4
36    
37     =cut
38    
39     package Coro;
40    
41     BEGIN {
42 root 1.5 $VERSION = 0.03;
43 root 1.1
44     require XSLoader;
45     XSLoader::load Coro, $VERSION;
46     }
47    
48 root 1.6 =item $coro = new [$coderef [, @args]]
49 root 1.1
50 root 1.6 Create a new coroutine and return it. The first C<transfer> call to this
51     coroutine will start execution at the given coderef. If, the subroutine
52     returns it will be executed again.
53    
54     If the coderef is omitted this function will create a new "empty"
55     coroutine, i.e. a coroutine that cannot be transfered to but can be used
56     to save the current coroutine in.
57 root 1.1
58     =cut
59    
60     sub new {
61     my $class = $_[0];
62 root 1.6 my $proc = $_[1] || sub { die "tried to transfer to an empty coroutine" };
63 root 1.1 bless _newprocess {
64     do {
65 root 1.6 eval { &$proc };
66 root 1.1 if ($@) {
67 root 1.6 $error_msg = $@;
68     $error_coro = _newprocess { };
69     &transfer($error_coro, $error);
70 root 1.1 }
71 root 1.4 } while (1);
72 root 1.1 }, $class;
73     }
74    
75 root 1.6 =item $prev->transfer($next)
76 root 1.1
77 root 1.7 Save the state of the current subroutine in C<$prev> and switch to the
78     coroutine saved in C<$next>.
79    
80     The "state" of a subroutine only ever includes scope, i.e. lexical
81     variables and the current execution state. It does not save/restore any
82     global variables such as C<$_> or C<$@> or any other special or non
83     special variables. So remember that every function call that might call
84     C<transfer> (such as C<Coro::Channel::put>) might clobber any global
85     and/or special variables. Yes, this is by design ;) You cna always create
86     your own process abstraction model that saves these variables.
87    
88     The easiest way to do this is to create your own scheduling primitive like this:
89    
90     sub schedule {
91     local ($_, $@, ...);
92     $old->transfer($new);
93     }
94 root 1.1
95     =cut
96    
97 root 1.6 # I call the _transfer function from a perl function
98 root 1.5 # because that way perl saves all important things on
99 root 1.7 # the stack. Actually, I'd do it from within XS, but
100     # I couldn't get it to work.
101 root 1.6 sub transfer {
102     _transfer($_[0], $_[1]);
103 root 1.1 }
104 root 1.6
105     =item $error, $error_msg, $error_coro
106    
107     This coroutine will be called on fatal errors. C<$error_msg> and
108     C<$error_coro> return the error message and the error-causing coroutine
109     (NOT an object) respectively. This API might change.
110    
111     =cut
112    
113     $error_msg =
114     $error_coro = undef;
115    
116     $error = _newprocess {
117     print STDERR "FATAL: $error_msg\nprogram aborted\n";
118     exit 50;
119     };
120 root 1.1
121     1;
122    
123     =back
124    
125     =head1 BUGS
126    
127     This module has not yet been extensively tested.
128 root 1.2
129     =head1 SEE ALSO
130    
131     L<Coro::Process>, L<Coro::Signal>.
132 root 1.1
133     =head1 AUTHOR
134    
135     Marc Lehmann <pcg@goof.com>
136     http://www.goof.com/pcg/marc/
137    
138     =cut
139