ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro/Cont.pm
Revision: 1.14
Committed: Mon Sep 24 00:51:19 2001 UTC (22 years, 8 months ago) by root
Branch: MAIN
Changes since 1.13: +2 -0 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 =head1 NAME
2
3 Coro::Cont - schmorp's faked continuations
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 no warnings;
33
34 use Carp qw(croak);
35
36 use Coro::State;
37 use Coro::Specific;
38
39 use base 'Exporter';
40
41 $VERSION = 0.5;
42 @EXPORT = qw(csub yield);
43
44 {
45 my @csub;
46
47 # this way of handling attributes simply is NOT scalable ;()
48 sub import {
49 Coro::Cont->export_to_level(1, @_);
50 my $old = *{(caller)[0]."::MODIFY_CODE_ATTRIBUTES"}{CODE};
51 no warnings;
52 *{(caller)[0]."::MODIFY_CODE_ATTRIBUTES"} = sub {
53 my ($package, $ref) = (shift, shift);
54 my @attrs;
55 for (@_) {
56 if ($_ eq "Cont") {
57 push @csub, [$package, $ref];
58 } else {
59 push @attrs, $_;
60 }
61 }
62 return $old ? $old->($package, $ref, @attrs) : @attrs;
63 };
64 }
65
66 sub findsym {
67 no warnings;
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 no warnings;
80 my $ref = findsym(@$_)
81 or croak "package $package: cannot declare non-global subs as 'Cont'";
82 *$ref = &csub($_->[1]);
83 }
84 @csub = ();
85 }
86 }
87
88 =item csub { ... }
89
90 Create a new "continuation" (when the sub falls of the end it is being
91 terminated).
92
93 =cut
94
95 our $return = new Coro::Specific;
96
97 sub csub(&) {
98 my $code = $_[0];
99 my $prev = new Coro::State;
100
101 my $coro = new Coro::State sub {
102 # we do this superfluous switch just to
103 # avoid the parameter passing problem
104 # on the first call
105 &yield;
106 &$code while 1;
107 };
108
109 # call it once
110 push @$$return, [$coro, $prev];
111 &Coro::State::transfer($prev, $coro, 0);
112
113 sub {
114 push @$$return, [$coro, $prev];
115 &Coro::State::transfer($prev, $coro, 0);
116 wantarray ? @_ : $_[0];
117 };
118 }
119
120 =item @_ = yield [list]
121
122 Return the given list/scalar as result of the continuation. Also returns
123 the new arguments given to the subroutine on the next call.
124
125 =cut
126
127 # implemented in Coro/State.xs
128 #sub yield(@) {
129 # &Coro::State::transfer(@{pop @$$return}, 0);
130 # wantarray ? @_ : $_[0];
131 #}
132
133 1;
134
135 =back
136
137 =head1 AUTHOR
138
139 Marc Lehmann <pcg@goof.com>
140 http://www.goof.com/pcg/marc/
141
142 =cut
143