Can I synchronously relinquish control to the event loop?

Fulko Hew fulko.hew at gmail.com
Mon Feb 27 21:28:18 CET 2012


On Mon, Feb 27, 2012 at 12:25 PM, Marc Lehmann <schmorp at schmorp.de> wrote:

> On Mon, Feb 27, 2012 at 11:01:54AM -0500, Fulko Hew <fulko.hew at gmail.com>
> wrote:
> > And this seems to be causing networking difficulties because
> > of either the amount of TX queuing, or RX queueing going on.
>
> what kind of difficulties? at least ae::handle lets you queue as much as
> you want - it might not be wise to do so (because ae::handle has to buffer
> all the data in memory), but perfectly possible.
>

"It appears that one or both ends fail so send some stuff or receive stuff."

My mainline (that I'm having issues with) in psuedo-code is

while (<>) {
   request_thing_allocation(\&allocate_complete_cb, \%thing_data);
}

sub request_thing_allocation {
   # remember_cb_and_data(@_);
   push_write('allocate_request');  # register_thing_cb() is invoked when
the response occurs
   ...
}

sub allocate_complete_cb {
  my ($allocate_response, $thing_data_ref) = @_;

  my $thing = Thing->new($allocate_response);
  $thing->populate($thing_data);
  push_write('register_thing);
}

so intuitively I'd expect the flow to go:
allocate_request 1 ->
                   <- allocate_response 1
register request 1 ->
                   <- register response 1
...
allocate n         ->
                   <- allocate_response n
register n         ->
                   <- register response n

but instead I see on Wireshark something similar to:

allocate 1 ->
...
allocate n ->
           <- allocate response 1
              ...
           <- allocate response n
register 1 ->
...
register n ->
           <- register response 1
              ...
           <- register response n

Ie. No receives are processed till all requests are sent.


 > So my first thought was, how can I, in my part 1 loop, allow
> > the eventloop to detect and process transmits and receives,
> > and when idle, let me (my current processing loop) continue?
>
> I don't understand your problem well enough - for me, it sounds more as
> if you want some event that tells you "now you can push more data", and
> indeed, AE::Handle has such an event callback, called "on_drain" - the
> on_drain callback is called whenever the (ae::handle) write buffer is
> empty, and you can write more.
>

That was my first suspicion, but then,after adding/playing-with:

 Coro::AnyEvent::idle;
 Coro::AnyEvent::poll;
 Coro::AnyEvent::sleep 0.001;

I found that I _could_ get things to 'interleave' by placing a
Coro::AnyEvent::sleep 0.001;  following each of my allocate request
thereby (artificially slowing things down) allowing one or both ends
to 'process' and thereby also allowing the response to be
'received and processed'. (calling idle or poll didn't affect the flow)

 > My second thought was that somehow Coro can come to my
> > rescue, but I don't understand how I can merge the two
> > together, and what I need to do in my mainline and timer callback
> > to get it to work.
>
> If your problem is that you have this kind of code:
>   while (read more file data...)
>      push_write
>
> and you want to "slow down" this loop to not be considerably faster then
> your
> network connection can send data, then, with coro, you can do that:
>
  sub wait_for_on_drain {
>      my ($handle) = @_;
>
>      $handle->on_drain (Coro::rouse_cb);
>      Coro::rouse_wait;
>      $handle->on_drain (undef);
>   }
>
> ... snip ...

This and the other example didn't affect the apparent processing flow
either.


>
>   async {
>      while (...
>   };
>
> Also, event processing will continue for everybody else with the above
> solution, which is *probably* what you want anyway.
>

I haven't tried this yet, but...
In the mean time what I did do was code up something that would:
- queue up my requests, and then one at a time...
  - peel them off a list, and
  - daisy-chain the 'register' to the end of the 'allocate response'
processing, and
  - daisy-chain the 'next allocate' onto the end of the 'register response'
processing.

This now causes both ends to behave in that intuitive manner and
avoids 'whatever the problem was', with the downside of a more
complex/non-intuitive algorithm/processing.

I'll look and see if async { ...} alters the flow.
Thanks for that suggestion.

Fulko
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.schmorp.de/pipermail/anyevent/attachments/20120227/f9dd7dc9/attachment.html>


More information about the anyevent mailing list