Hyperman

 view release on metacpan or  search on metacpan

xs/future.xs  view on Meta::CPAN

    OUTPUT:
        RETVAL

int
is_failed(self)
    SV *self
    CODE:
        RETVAL = hmf_state(aTHX_ self) == HMF_FAILED;
    OUTPUT:
        RETVAL

int
is_cancelled(self)
    SV *self
    CODE:
        RETVAL = hmf_state(aTHX_ self) == HMF_CANCELLED;
    OUTPUT:
        RETVAL

SV *
on_ready(self, cb)
    SV *self
    SV *cb
    CODE:
        hmf_on_ready(aTHX_ self, cb);
        RETVAL = SvREFCNT_inc(self);
    OUTPUT:
        RETVAL

SV *
on_done(self, usercb)
    SV *self
    SV *usercb
    ALIAS:
        on_fail = 1
    CODE:
    {
        SV *cb = hm_closure(aTHX_ hm_xs_ondone_cb, NULL, usercb, NULL, NULL,
                            ix == 0 ? HMF_DONE : HMF_FAILED, 0);
        hmf_on_ready(aTHX_ self, cb);
        SvREFCNT_dec(cb);
        RETVAL = SvREFCNT_inc(self);
    }
    OUTPUT:
        RETVAL

SV *
await(self)
    SV *self
    CODE:
        hmf_await(aTHX_ self);
        RETVAL = SvREFCNT_inc(self);
    OUTPUT:
        RETVAL

void
get(self)
    SV *self
    ALIAS:
        result = 1
    PPCODE:
    {
        IV st;
        PERL_UNUSED_VAR(ix);
        hmf_await(aTHX_ self);
        st = hmf_state(aTHX_ self);
        if (st == HMF_FAILED) {
            AV *fav = hmf_values_av(aTHX_ self);
            SV **e = fav ? av_fetch(fav, 0, 0) : NULL;
            if (e) croak_sv(sv_mortalcopy(*e));
            croak("Failed");
        }
        if (st == HMF_CANCELLED)
            croak("Hyperman::Future was cancelled");
        {
            AV *rav = hmf_values_av(aTHX_ self);
            SSize_t n = rav ? av_len(rav) + 1 : 0;
            if (GIMME_V == G_ARRAY) {
                SSize_t i;
                EXTEND(SP, n);
                for (i = 0; i < n; i++) {
                    SV **e = av_fetch(rav, i, 0);
                    PUSHs(e ? sv_mortalcopy(*e) : &PL_sv_undef);
                }
            } else if (n) {
                SV **e = av_fetch(rav, 0, 0);
                XPUSHs(e ? sv_mortalcopy(*e) : &PL_sv_undef);
            } else {
                XPUSHs(&PL_sv_undef);
            }
        }
    }

void
failure(self)
    SV *self
    PPCODE:
    {
        hmf_await(aTHX_ self);
        if (hmf_state(aTHX_ self) != HMF_FAILED) XSRETURN_EMPTY;
        {
            AV *fav = hmf_values_av(aTHX_ self);
            SSize_t n = fav ? av_len(fav) + 1 : 0;
            if (GIMME_V == G_ARRAY) {
                SSize_t i;
                EXTEND(SP, n);
                for (i = 0; i < n; i++) {
                    SV **e = av_fetch(fav, i, 0);
                    PUSHs(e ? sv_mortalcopy(*e) : &PL_sv_undef);
                }
            } else if (n) {
                SV **e = av_fetch(fav, 0, 0);
                XPUSHs(e ? sv_mortalcopy(*e) : &PL_sv_undef);
            }
        }
    }

# result/failure values as a plain list, no dying, no awaiting.
void
_values(self)
    SV *self
    PPCODE:
    {
        AV *rav = hmf_values_av(aTHX_ self);
        SSize_t i, n = rav ? av_len(rav) + 1 : 0;
        EXTEND(SP, n);
        for (i = 0; i < n; i++) {
            SV **e = av_fetch(rav, i, 0);
            PUSHs(e ? sv_mortalcopy(*e) : &PL_sv_undef);
        }
    }

# ---- chaining ----

SV *
then(self, ...)
    SV *self
    ALIAS:
        else = 1
    CODE:
    {
        SV *on_done = NULL, *on_fail = NULL;
        SV *cb;
        if (ix == 0) {   /* then($ok?, $err?) */
            if (items > 1 && SvOK(ST(1))) on_done = ST(1);
            if (items > 2 && SvOK(ST(2))) on_fail = ST(2);
        } else {         /* else($err) */
            if (items > 1 && SvOK(ST(1))) on_fail = ST(1);
        }
        RETVAL = hmf_new(aTHX_ hmf_class_of(aTHX_ self));
        hmf_set_upstream(aTHX_ RETVAL, self);
        cb = hm_closure(aTHX_ hm_xs_then_cb, RETVAL, on_done, on_fail, NULL, 0, 0);
        hmf_on_ready(aTHX_ self, cb);
        SvREFCNT_dec(cb);
    }
    OUTPUT:
        RETVAL

SV *
followed_by(self, usercb)
    SV *self
    SV *usercb
    CODE:
    {
        SV *cb;
        RETVAL = hmf_new(aTHX_ hmf_class_of(aTHX_ self));
        hmf_set_upstream(aTHX_ RETVAL, self);
        cb = hm_closure(aTHX_ hm_xs_then_cb, RETVAL, usercb, NULL, NULL, 1, 0);
        hmf_on_ready(aTHX_ self, cb);
        SvREFCNT_dec(cb);
    }
    OUTPUT:
        RETVAL

SV *
transform(self, ...)
    SV *self
    CODE:
    {
        SV *xd = NULL, *xf = NULL;
        SV *cb;
        int i;



( run in 0.968 second using v1.01-cache-2.11-cpan-92ad3014f07 )