Async-Trampoline
view release on metacpan or search on metacpan
lib/Async/Trampoline.xs++ view on Meta::CPAN
continuation = async_from_sv(aTHX_ (SV*) data.at(0));
if (!continuation)
throw std::runtime_error(
"generator Async must have Async as first value");
AsyncRef next_map = make_gen_map(
aTHX_
std::move(continuation), InvokeCV(body));
DestructibleTuple body_args = destructible_tuple_tail(1, data);
AsyncRef result = body(body_args);
return make_async_yield(aTHX_ std::move(next_map), std::move(result));
}
} gen_map_thunk { std::move(body) };
AsyncRef await = Async::alloc();
await->set_to_Thunk(gen_map_thunk, std::move(gen));
return await;
}
static AsyncRef concat_fold_right(pTHX_ ssize_t i, AV* array)
{
if (i > av_len(array))
return nullptr;
AsyncRef left;
if (SV** left_sv = av_fetch(array, i, 0))
left = async_from_sv(aTHX_ *left_sv);
if (!left)
throw std::runtime_error(
"all dependencies must be Asyncs");
AsyncRef right = concat_fold_right(aTHX_ i + 1, array);
if (!right)
return left;
AsyncRef concat = Async::alloc();
concat->set_to_Concat(std::move(left), std::move(right));
return concat;
};
#define ASYNC_TYPE_GET(name) (static_cast<I32>(Async_Type::name))
#define ASYNC_TYPE_CATEGORY_COMPLETE ASYNC_TYPE_GET(CATEGORY_COMPLETE)
#define ASYNC_TYPE_CATEGORY_RESOLVED ASYNC_TYPE_GET(CATEGORY_RESOLVED)
#define ASYNC_TYPE_IS_CANCEL ASYNC_TYPE_GET(IS_CANCEL)
#define ASYNC_TYPE_IS_ERROR ASYNC_TYPE_GET(IS_ERROR)
#define ASYNC_TYPE_IS_VALUE ASYNC_TYPE_GET(IS_VALUE)
MODULE = Async::Trampoline PACKAGE = Async::Trampoline
void
Async::run_until_completion()
INIT:
CXX_TRY
PPCODE:
{
Async_run_until_completion(THIS);
Async& result = THIS->ptr_follow();
if (!result.has_category(Async_Type::CATEGORY_COMPLETE))
{
croak( "run_until_completion() did not complete " ASYNC_FORMAT,
ASYNC_FORMAT_ARGS(&result));
}
else if (result.has_type(Async_Type::IS_CANCEL))
{
croak("run_until_completion(): Async was cancelled");
}
else if (result.has_type(Async_Type::IS_ERROR))
{
croak_sv((SV*) result.as_error.data);
}
else if (result.has_type(Async_Type::IS_VALUE))
{
ASYNC_LOG_DEBUG("returning to Perl: " ASYNC_FORMAT "\n",
ASYNC_FORMAT_ARGS(&result));
DestructibleTuple& values = result.as_value;
XSprePUSH; // to fix weird XS+PPCODE argument handling
EXTEND(SP, static_cast<ssize_t>(values.size));
for (auto value : values)
{
ASYNC_LOG_DEBUG(" - " DESTRUCTIBLE_FORMAT "\n",
DESTRUCTIBLE_FORMAT_ARGS_BORROWED(values.vtable, value));
PUSHs(sv_mortalcopy((SV*) value));
}
ASYNC_LOG_DEBUG("result end\n");
XSRETURN(values.size);
}
else
{
assert(0);
}
}
CXX_CATCH
void
Async::DESTROY()
INIT:
CXX_TRY
CODE:
THIS->unref();
CLEANUP:
CXX_CATCH
Async*
async(body)
CV* body
PROTOTYPE: &
INIT:
CXX_TRY
CODE:
{
AsyncRef self = Async::alloc();
self->set_to_Thunk(InvokeCV{aTHX_ body}, nullptr);
RETVAL = std::move(self).ptr_with_ownership();
}
OUTPUT: RETVAL
CLEANUP:
CXX_CATCH
Async*
await(deps, body)
SV* deps
CV* body
PROTOTYPE: $&
INIT:
CXX_TRY
CODE:
{
auto get_arrayref = [](SV* sv) -> AV*
{
if (!SvROK(sv))
return nullptr;
sv = SvRV(sv);
( run in 0.682 second using v1.01-cache-2.11-cpan-71847e10f99 )