1 | =head1 NAME |
1 | =head1 NAME |
2 | |
2 | |
3 | Coro - create an manage coroutines |
3 | Coro - create and manage coroutines |
4 | |
4 | |
5 | =head1 SYNOPSIS |
5 | =head1 SYNOPSIS |
6 | |
6 | |
7 | use Coro; |
7 | use Coro; |
8 | |
8 | |
|
|
9 | $new = new Coro sub { |
|
|
10 | print "in coroutine, switching back\n"; |
|
|
11 | $Coro::main->resume; |
|
|
12 | print "in coroutine again, switching back\n"; |
|
|
13 | $Coro::main->resume; |
|
|
14 | }; |
|
|
15 | |
|
|
16 | print "in main, switching to coroutine\n"; |
|
|
17 | $new->resume; |
|
|
18 | print "back in main, switch to coroutine again\n"; |
|
|
19 | $new->resume; |
|
|
20 | print "back in main\n"; |
|
|
21 | |
9 | =head1 DESCRIPTION |
22 | =head1 DESCRIPTION |
|
|
23 | |
|
|
24 | This module implements coroutines. Coroutines, similar to continuations, |
|
|
25 | allow you to run more than one "thread of execution" in parallel. Unlike |
|
|
26 | threads this, only voluntary switching is used so locking problems are |
|
|
27 | greatly reduced. |
|
|
28 | |
|
|
29 | Although this is the "main" module of the Coro family it provides only |
|
|
30 | low-level functionality. See L<Coro::Process> and related modules for a |
|
|
31 | more useful process abstraction including scheduling. |
10 | |
32 | |
11 | =over 4 |
33 | =over 4 |
12 | |
34 | |
13 | =cut |
35 | =cut |
14 | |
36 | |
15 | package Coro; |
37 | package Coro; |
16 | |
38 | |
17 | BEGIN { |
39 | BEGIN { |
18 | $VERSION = 0.01; |
40 | $VERSION = 0.03; |
19 | |
41 | |
20 | require XSLoader; |
42 | require XSLoader; |
21 | XSLoader::load Coro, $VERSION; |
43 | XSLoader::load Coro, $VERSION; |
22 | } |
44 | } |
23 | |
45 | |
… | |
… | |
45 | |
67 | |
46 | $error_msg = |
68 | $error_msg = |
47 | $error_coro = undef; |
69 | $error_coro = undef; |
48 | |
70 | |
49 | $error = _newprocess { |
71 | $error = _newprocess { |
50 | print STDERR "FATAL: $error_msg, program aborted\n"; |
72 | print STDERR "FATAL: $error_msg\nprogram aborted\n"; |
51 | exit 250; |
73 | exit 250; |
52 | }; |
74 | }; |
53 | |
75 | |
54 | =item $coro = new $coderef [, @args] |
76 | =item $coro = new $coderef [, @args] |
55 | |
77 | |
… | |
… | |
68 | eval { &$proc->resume }; |
90 | eval { &$proc->resume }; |
69 | if ($@) { |
91 | if ($@) { |
70 | ($error_msg, $error_coro) = ($@, $current); |
92 | ($error_msg, $error_coro) = ($@, $current); |
71 | $error->resume; |
93 | $error->resume; |
72 | } |
94 | } |
73 | } while (); |
95 | } while (1); |
74 | }, $class; |
96 | }, $class; |
75 | } |
97 | } |
76 | |
98 | |
77 | =item $coro->resume |
99 | =item $coro->resume |
78 | |
100 | |
… | |
… | |
80 | |
102 | |
81 | =cut |
103 | =cut |
82 | |
104 | |
83 | my $prev; |
105 | my $prev; |
84 | |
106 | |
|
|
107 | # I call the _transfer function from a pelr function |
|
|
108 | # because that way perl saves all important things on |
|
|
109 | # the stack. |
85 | sub resume { |
110 | sub resume { |
86 | $prev = $current; $current = $_[0]; |
111 | $prev = $current; $current = $_[0]; |
87 | _transfer($prev, $current); |
112 | _transfer($prev, $current); |
88 | } |
113 | } |
89 | |
114 | |
… | |
… | |
93 | |
118 | |
94 | =head1 BUGS |
119 | =head1 BUGS |
95 | |
120 | |
96 | This module has not yet been extensively tested. |
121 | This module has not yet been extensively tested. |
97 | |
122 | |
|
|
123 | =head1 SEE ALSO |
|
|
124 | |
|
|
125 | L<Coro::Process>, L<Coro::Signal>. |
|
|
126 | |
98 | =head1 AUTHOR |
127 | =head1 AUTHOR |
99 | |
128 | |
100 | Marc Lehmann <pcg@goof.com> |
129 | Marc Lehmann <pcg@goof.com> |
101 | http://www.goof.com/pcg/marc/ |
130 | http://www.goof.com/pcg/marc/ |
102 | |
131 | |