All right, the key word "flow" has been uttered. Here's the flow:

1. lambda {X} has just been called. It returns an empty object, blessed hash of IO::Lambda with a single coderef X, which is not executed yet. This object has a method wait(), which is then called.

2. wait() figures out that lambda (object, that is) hasn't been started yet. It switches the lambda into "started" state, and invokes callback X. Then it enters event loop sleep/select cycle, until the lambda state gets "finished":

sub wait # simplified { my $lambda = shift; $lambda-> start if $lambda-> is_passive; event_loop while not $lambda-> is_finished; return $lambda-> peek; }

3. Coderef X creates a socket, calls a non-blocking TCP connect on it using IO::Socket::new, and passes that socket, along with a coderef Y to standard condition writable:

context $socket; writable { Y }
and then exits. The lambda state is unchanged by calling writable, however it adds the socket into the listening queue of the underlying event loop (select, AnyEvent, POE, whatever), and asks the loop to do something when that socket gets writable. Meanwhile, wait still processes the event loop.

4. TCP syn-synack-ack succeeded, event loop says the socket is writable, and calls the lambda that waits for the socket. Lambda figures out that the socket waiting conditions should result in calling the coderef Y, which it immediately does.

5. Coderef Y does two things: it prints to the socket, and registers another coderef Z, that will be called when the socket gets readable:

syswrite $socket ....; readable { Z }
Note, that these callbacks are one-shot only. The subscription to the writable events is not renewed, so the socket is not listened for write events anymore.

6. Socket gets readable, Z gets executed. It reads some bytes, but wants more, so it re-subscribes on the same socket, with the same coderef Z, to be woken up when there are more data. This is done with calling again. The latter knows the last coderef used, and spares the programmer from calling readable with the same coderef.

7. Socket gets readable, Z gets executed again. It reads zero bytes, figures it's an EOF, it says "return $buf". Before that, result of the last executed coderef was accumulated inside the lambda object. Now, $buf overwrites that and is stores its own $buf, which is then accessible through method peek.

8. Lambda, having called coderef Z, finds out that it has no more subscriptions, so it switches itself to "finished" state.

9. wait sees that the lambda is finished, it stops the cycle and and returns whatever was left on lambda, in our case $buf.

I almost feel how it gets better :) Please tell me what do you think.


In reply to Re^3: regarding 1.02 (was Re: IO::Lambda: call for participation) by dk
in thread IO::Lambda: call for participation by dk

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.