1 |
From: Marc Lehmann |
2 |
To: "Eric G. Bergeron" |
3 |
Subject: Re: About the Coro module |
4 |
|
5 |
> I am starting to use your perl Coro module and I think that I noticed a |
6 |
|
7 |
Well, perl is not really coro-safe, or was it that coro is not perl-safe? |
8 |
:) |
9 |
|
10 |
It should work, but some corner cases, especially at global destruction, |
11 |
are not handled as nice as they could. |
12 |
|
13 |
> bug (I just don't know where the bug is.). This code below seems to run the |
14 |
> function 1 time too many. |
15 |
> |
16 |
> use Coro; |
17 |
> use strict; |
18 |
> my $proc=new Coro sub |
19 |
> { my $i=0; |
20 |
> while (1) |
21 |
> { print "$i "; $i++; |
22 |
> cede; |
23 |
> } |
24 |
> }; |
25 |
> $proc->ready(); |
26 |
> cede; |
27 |
> $proc->ready(); |
28 |
> cede; |
29 |
|
30 |
no, that's correct. "cede" is like the posix "yield" function. It |
31 |
doesn't take the process out of the ready queue, it just gives other |
32 |
processes the opportunity to run. |
33 |
|
34 |
So a single ->ready suffices to make it run as often as it wants - until |
35 |
the main program exits, that is. |
36 |
|
37 |
The second ->ready call is actually a bug (not fatal), as it puts the |
38 |
process a second time into the run queue. This is not a problem for |
39 |
Coro, but not expected by you :) |
40 |
|
41 |
If you want to switch to another coro _without_ being put into the ready |
42 |
queue automatically, don't use "cede" but "schedule". Schedule just |
43 |
switches to another process and leaves the current one alone, while cede |
44 |
is just a temporary switch - it will return later. |
45 |
|
46 |
Think of coros as processes. The Coro::State and Coro::Cont modules |
47 |
implement different ideas, so you could roll your own stuff if you really |
48 |
wanted to. |
49 |
|
50 |
A simple (althogh difficult to read) example is in one of the many |
51 |
semaphore modules (e.g. Coro::Signal). The wait method for example: |
52 |
|
53 |
sub wait { |
54 |
if ($_[0][0]) { |
55 |
$_[0][0] = 0; |
56 |
} else { |
57 |
push @{$_[0][1]}, $Coro::current; # <- here |
58 |
Coro::schedule; # <- here |
59 |
} |
60 |
} |
61 |
|
62 |
It first remembers the "current" process (the calling coro) internally |
63 |
and then calls schedule, which cuases the process to stop running |
64 |
immediately. Unless somebody else wakes it up it'll never run again. |
65 |
"send" does this: |
66 |
|
67 |
sub send { |
68 |
if (@{$_[0][1]}) { |
69 |
(shift @{$_[0][1]})->ready; # <- here |
70 |
} else { |
71 |
$_[0][0] = 1; |
72 |
} |
73 |
} |
74 |
|
75 |
It puts the waiting process into thr ready queue again. |
76 |
|
77 |
"cede" is implemented like this (in C, but the basic idea is the same): |
78 |
|
79 |
sub cede { |
80 |
$current->ready; |
81 |
schedule; |
82 |
} |
83 |
|
84 |
so it put's itself into the ready queue and calls the scheduler. |
85 |
|
86 |
-- |
87 |
-----==- | |
88 |
----==-- _ | |
89 |
---==---(_)__ __ ____ __ Marc Lehmann +-- |
90 |
--==---/ / _ \/ // /\ \/ / pcg@goof.com |e| |
91 |
-=====/_/_//_/\_,_/ /_/\_\ XX11-RIPE --+ |
92 |
The choice of a GNU generation | |
93 |
| |
94 |
|