ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro/Cont.pm
Revision: 1.49
Committed: Fri Dec 1 19:58:53 2006 UTC (17 years, 5 months ago) by root
Branch: MAIN
CVS Tags: HEAD
Changes since 1.48: +0 -0 lines
State: FILE REMOVED
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 &$cont, %hash1;
15
16 # dasselbe in grĂ¼n (as the 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
38 use vars qw($return);
39
40 use base 'Exporter';
41
42 $VERSION = 1.9;
43 @EXPORT = qw(csub yield);
44
45 {
46 my @csub;
47
48 # this way of handling attributes simply is NOT scalable ;()
49 sub import {
50 Coro::Cont->export_to_level(1, @_);
51 my $old = *{(caller)[0]."::MODIFY_CODE_ATTRIBUTES"}{CODE};
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 my ($pkg, $ref) = @_;
68 my $type = ref $ref;
69 for my $sym (values %{$pkg."::"}) {
70 return \$sym if *{$sym}{$type} == $ref;
71 }
72 ();
73 }
74
75 sub INIT {
76 # prototypes are currently being ignored
77 for (@csub) {
78 my $ref = findsym(@$_)
79 or croak "package $package: cannot declare non-global subs as 'Cont'";
80 *$ref = &csub($_->[1]);
81 }
82 @csub = ();
83 }
84 }
85
86 =item csub { ... }
87
88 Create a new "continuation" (when the sub falls off the end it is being
89 terminated).
90
91 =cut
92
93 sub csub(&) {
94 my $code = $_[0];
95 my $prev = new Coro::State;
96
97 my $coro = new Coro::State sub {
98 # we do this superfluous switch just to
99 # avoid the parameter passing problem
100 # on the first call
101 &yield;
102 &$code while 1;
103 };
104
105 # call it once
106 push @{ $Coro::current->{yieldstack} }, [$coro, $prev];
107 Coro::State::transfer ($prev, $coro, 0);
108
109 sub {
110 push @{ $Coro::current->{yieldstack} }, [$coro, $prev];
111 Coro::State::transfer ($prev, $coro, 0);
112 wantarray ? @_ : $_[0];
113 };
114 }
115
116 =item @_ = yield [list]
117
118 Return the given list/scalar as result of the continuation. Also returns
119 the new arguments given to the subroutine on the next call.
120
121 =cut
122
123 # implemented in Coro/State.xs
124 #sub yield(@) {
125 # &Coro::State::transfer(@{pop @$$return}, 0);
126 # wantarray ? @_ : $_[0];
127 #}
128
129 1;
130
131 =back
132
133 =head1 AUTHOR
134
135 Marc Lehmann <schmorp@schmorp.de>
136 http://home.schmorp.de/
137
138 =cut
139