Search code examples
perlanyevent

How to make anyevent "sequential"?


I would like to try mix of AnyEvent and Coro.
Is there a way to make the three lines between BEGIN and END more elegant/condensed?

use AnyEvent::HTTP;
use Coro;

async {
  _
  # BEGIN
  my $READY = AnyEvent->condvar;
  my $guard = http_request( GET => $url, $READY );
  my ($data, $hHeaders ) = $READY->recv;
  # END
  …
}

WARNING: man AnyEvent suggest slightly different way for Coro integration but the general idea stays the same (comment added after accepted reply).

AnyEvent::HTTP::http_get "url", Coro::rouse_cb;
my ($body, $hdr) = Coro::rouse_wait;

Solution

  • Subs. This is what subs are for.

    sub sync {
       my $sub = shift;
       $sub = \&$sub;   # Make `strict refs` happy.
       my $done = AnyEvent->condvar;
       my $guard = $sub->( @_, $done );
       return $done->recv;
    }
    
    my ( $data, $headers ) = sync \&http_request, GET => $url;
      # -or-
    my ( $data, $headers ) = sync http_request => GET => $url;
    

    or

    use Sub::Name qw( sub_name );
    
    sub build_sync(_) {
       my $wrapped_sub_name = shift;
       my $wrapped_sub = \&$wrapped_sub_name;
    
       my $sub_name = $wrapped_sub_name . '_sync';
       my $sub = sub_name $sub_name => sub {
          my $done = AnyEvent->condvar;
          my $guard = $wrapped_sub->( @_, $done );
          return $done->recv;
       };
    
       no strict qw( refs );
       *$sub_name = $sub;
    }
    
    build_sync for qw( http_request ... );
    
    my ( $data, $headers ) = http_request_sync( GET => $url );