AE::postpone degenerates into synchronous behavior, intended?

Darin McBride darin.mcbride at shaw.ca
Tue Jan 1 05:28:33 CET 2013


On Monday December 31 2012 5:33:28 PM Michael Alan Dorman wrote:
> Hi, Marc,
> 
> I was working to patch Stevan Little's recently-released Promises
> library to always call callbacks asynchronously when running under
> AnyEvent.

Part of the problem here seems to me that you're calling "sleep".  If you want 
to insert a delay, I think you have to go with the timer.  And you need to 
stop calling sleep.

my $postponement; $postponement = sub {
  if ($postponements--) {
    print "iter $postponements\n";
    my $t; $t = AE::timer 2, 0, sub { undef $t; $postponement->() };
  }
};

But I don't think that's really what you want.  I think that if you simply 
remove the sleep, and if you actually have a loop going, you'll be fine.

For example:

use AnyEvent;

my $loop = AE::cv;
my $tick; $tick = AE::timer 0, 0.75, sub {
    print "tick\n";
};

my $postponements = 5;
my $postponement; $postponement = sub {
    if ($postponements--) {
        my $p = $postponements;
        print "iter $p\n";
        AE::postpone {
            print "postpone: $p\n";
            $postponement->();
        };
        print "done $p\n";
    } else {
        undef $tick;
        $loop->send();
    }
};
$postponement->();
$loop->recv;

The output from this looks like:

iter 4
done 4
tick
postpone: 4
iter 3
done 3
postpone: 3
iter 2
done 2
postpone: 2
iter 1
done 1
postpone: 1
iter 0
done 0
postpone: 0


Note how the postponed stuff is called after the done for the same value.  It 
is being postponed.  (There is only the one tick because there's no sleeping 
here.)  This does not look synchronous to me.  Though I'd probably end up 
using Coro to make this just a bit easier to insert those sleeps back in:

use AnyEvent;
use Coro;

my $loop = AE::cv;
my $tick; $tick = AE::timer 0, 0.75, sub {
    print "tick\n";
};

my $postponements = 5;
my $postponement; $postponement = sub {
    if ($postponements--) {
        my $p = $postponements;
        print "iter $p\n";
        async { # instead of AE::postpone
            print "postpone: $p\n";
            Coro::AnyEvent::sleep(2); # instead of sleep
            $postponement->();
        };
        print "done $p\n";
    } else {
        undef $tick;
        $loop->send();
    }
};
$postponement->();
$loop->recv;

And then the output looks like this:

iter 4
done 4
postpone: 4
tick
tick
tick
iter 3
done 3
postpone: 3
tick
tick
tick
iter 2
done 2
postpone: 2
tick
tick
tick
iter 1
done 1
postpone: 1
tick
tick
iter 0
done 0
postpone: 0
tick
tick
tick

Again notice how the postpones are all after their respective done's.




More information about the anyevent mailing list