ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro/Cont.pm
Revision: 1.35
Committed: Tue Feb 22 19:51:58 2005 UTC (19 years, 3 months ago) by root
Branch: MAIN
CVS Tags: rel-1_1
Changes since 1.34: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 =head1 NAME
2
3 Coro::Cont - continuations in perl
4
5 =head1 SYNOPSIS
6
7 use Coro::Cont;
8
9 # multiply all hash keys by 2
10 my $cont = csub {
11 yield $_*2;
12 yield $_;
13 };
14 my %hash2 = map &$csub, &hash1;
15
16 # dasselbe in grĂ¼n (as we germans say)
17 sub mul2 : Cont {
18 yield $_[0]*2;
19 yield $_[0];
20 }
21
22 my %hash2 = map mul2($_), &hash1;
23
24 =head1 DESCRIPTION
25
26 =over 4
27
28 =cut
29
30 package Coro::Cont;
31
32 BEGIN { eval { require warnings } && warnings->unimport }
33
34 use Carp qw(croak);
35
36 use Coro::State;
37 use Coro::Specific;
38
39 use vars qw($return);
40
41 use base 'Exporter';
42
43 $VERSION = 1.1;
44 @EXPORT = qw(csub yield);
45
46 {
47 my @csub;
48
49 # this way of handling attributes simply is NOT scalable ;()
50 sub import {
51 Coro::Cont->export_to_level(1, @_);
52 my $old = *{(caller)[0]."::MODIFY_CODE_ATTRIBUTES"}{CODE};
53 *{(caller)[0]."::MODIFY_CODE_ATTRIBUTES"} = sub {
54 my ($package, $ref) = (shift, shift);
55 my @attrs;
56 for (@_) {
57 if ($_ eq "Cont") {
58 push @csub, [$package, $ref];
59 } else {
60 push @attrs, $_;
61 }
62 }
63 return $old ? $old->($package, $ref, @attrs) : @attrs;
64 };
65 }
66
67 sub findsym {
68 my ($pkg, $ref) = @_;
69 my $type = ref $ref;
70 for my $sym (values %{$pkg."::"}) {
71 return \$sym if *{$sym}{$type} == $ref;
72 }
73 ();
74 }
75
76 sub INIT {
77 # prototypes are currently being ignored
78 for (@csub) {
79 my $ref = findsym(@$_)
80 or croak "package $package: cannot declare non-global subs as 'Cont'";
81 *$ref = &csub($_->[1]);
82 }
83 @csub = ();
84 }
85 }
86
87 =item csub { ... }
88
89 Create a new "continuation" (when the sub falls of the end it is being
90 terminated).
91
92 =cut
93
94 $return = new Coro::Specific;
95
96 sub csub(&) {
97 my $code = $_[0];
98 my $prev = new Coro::State;
99
100 my $coro = new Coro::State sub {
101 # we do this superfluous switch just to
102 # avoid the parameter passing problem
103 # on the first call
104 &yield;
105 &$code while 1;
106 };
107
108 # call it once
109 push @$$return, [$coro, $prev];
110 &Coro::State::transfer($prev, $coro, 0);
111
112 sub {
113 push @$$return, [$coro, $prev];
114 &Coro::State::transfer($prev, $coro, 0);
115 wantarray ? @_ : $_[0];
116 };
117 }
118
119 =item @_ = yield [list]
120
121 Return the given list/scalar as result of the continuation. Also returns
122 the new arguments given to the subroutine on the next call.
123
124 =cut
125
126 # implemented in Coro/State.xs
127 #sub yield(@) {
128 # &Coro::State::transfer(@{pop @$$return}, 0);
129 # wantarray ? @_ : $_[0];
130 #}
131
132 1;
133
134 =back
135
136 =head1 AUTHOR
137
138 Marc Lehmann <pcg@goof.com>
139 http://home.schmorp.de/
140
141 =cut
142