Hypersonic
view release on metacpan or search on metacpan
lib/Hypersonic/UA.pm view on Meta::CPAN
->line('SvREFCNT_inc(future);')
->endif
->blank
->line('PUTBACK;')
->line('FREETMPS; LEAVE;')
->blank
->comment('Start async request via Hypersonic::UA::Async')
->comment('Pass self_sv so start_request can auto-tick')
->line('ENTER; SAVETMPS;')
->line('PUSHMARK(SP);')
->line('XPUSHs(method_sv);')
->line('XPUSHs(url_sv);')
->line('XPUSHs(body_sv);')
->line('XPUSHs(future);')
->line('XPUSHs(self_sv);')
->line('PUTBACK;')
->blank
->line('count = call_pv("Hypersonic::UA::Async::start_request", G_SCALAR);')
->line('SPAGAIN;')
->blank
->line('int async_slot = -1;')
->if('count > 0')
->line('async_slot = POPi;')
->endif
->blank
->line('PUTBACK;')
->line('FREETMPS; LEAVE;')
->blank
->comment('Store async slot in UA for polling')
->if('async_slot >= 0')
->comment('Associate slot with self for run() to find')
->line('HV *ua_hv = (HV *)SvRV(self_sv);')
->line('AV *pending_av;')
->line('SV **pending_svp = hv_fetch(ua_hv, "_async_pending", 14, 0);')
->if('pending_svp && SvROK(*pending_svp)')
->line('pending_av = (AV *)SvRV(*pending_svp);')
->else
->line('pending_av = newAV();')
->line('hv_store(ua_hv, "_async_pending", 14, newRV_noinc((SV *)pending_av), 0);')
->endif
->line('av_push(pending_av, newSViv(async_slot));')
->endif
->blank
->line('ST(0) = sv_2mortal(future);')
->xs_return('1')
->xs_end
->blank;
}
sub gen_xs_run {
my ($class, $builder) = @_;
$builder->comment('Run all pending async requests to completion')
->xs_function('xs_ua_run')
->xs_preamble
->line('if (items < 1) croak("Usage: $ua->run()");')
->blank
->line('SV *self_sv = ST(0);')
->blank
->comment('Poll until all pending requests complete')
->line('int iterations = 0;')
->line('int max_iterations = 10000;')
->blank
->line('SPAGAIN;')
->line('while (iterations++ < max_iterations) {')
->line(' ENTER; SAVETMPS;')
->line(' PUSHMARK(SP);')
->line(' XPUSHs(self_sv);')
->line(' PUTBACK;')
->blank
->line(' call_method("pending", G_SCALAR);')
->line(' SPAGAIN;')
->blank
->line(' int pending = POPi;')
->line(' PUTBACK;')
->line(' FREETMPS; LEAVE;')
->blank
->line(' if (pending == 0) break;')
->blank
->comment(' Tick once')
->line(' ENTER; SAVETMPS;')
->line(' PUSHMARK(SP);')
->line(' XPUSHs(self_sv);')
->line(' PUTBACK;')
->line(' call_method("tick", G_DISCARD);')
->line(' FREETMPS; LEAVE;')
->line('}')
->blank
->xs_return('0')
->xs_end
->blank;
}
sub gen_xs_run_one {
my ($class, $builder) = @_;
$builder->comment('Run one async request to completion')
->xs_function('xs_ua_run_one')
->xs_preamble
->line('if (items < 2) croak("Usage: $ua->run_one($future)");')
->blank
->line('SV *self_sv = ST(0);')
->line('SV *future_sv = ST(1);')
->blank
->comment('Poll until this specific future resolves')
->line('int iterations = 0;')
->line('int max_iterations = 10000;')
->blank
->line('SPAGAIN;')
->line('while (iterations++ < max_iterations) {')
->comment(' Check if future is done')
->line(' ENTER; SAVETMPS;')
->line(' PUSHMARK(SP);')
->line(' XPUSHs(future_sv);')
->line(' PUTBACK;')
->blank
->line(' call_method("is_ready", G_SCALAR);')
->line(' SPAGAIN;')
->blank
->line(' int ready = POPi;')
->line(' PUTBACK;')
->line(' FREETMPS; LEAVE;')
->blank
->line(' if (ready) break;')
->blank
->comment(' Tick once')
->line(' ENTER; SAVETMPS;')
->line(' PUSHMARK(SP);')
->line(' XPUSHs(self_sv);')
->line(' PUTBACK;')
->line(' call_method("tick", G_DISCARD);')
->line(' FREETMPS; LEAVE;')
->line('}')
->blank
->comment('Return the future result')
->line('ENTER; SAVETMPS;')
->line('PUSHMARK(SP);')
->line('XPUSHs(future_sv);')
->line('PUTBACK;')
->blank
->line('call_method("get", G_SCALAR);')
->line('SPAGAIN;')
->blank
->line('SV *result = POPs;')
->line('SvREFCNT_inc(result);')
->line('PUTBACK;')
->line('FREETMPS; LEAVE;')
->blank
->line('ST(0) = sv_2mortal(result);')
->xs_return('1')
->xs_end
->blank;
}
sub gen_xs_parallel {
my ($class, $builder) = @_;
$builder->comment('Run multiple requests in parallel, wait for all')
->xs_function('xs_ua_parallel')
->xs_preamble
->line('int i;')
->line('if (items < 2) croak("Usage: $ua->parallel(@futures)");')
->blank
->line('SV *self_sv = ST(0);')
->blank
->comment('Collect futures')
->line('AV *futures = newAV();')
->line('for (i = 1; i < items; i++) {')
->line(' av_push(futures, SvREFCNT_inc(ST(i)));')
->line('}')
( run in 2.004 seconds using v1.01-cache-2.11-cpan-4ab04211f4c )