Data-SortedSet-Shared

 view release on metacpan or  search on metacpan

Shared.xs  view on Meta::CPAN

    int found = ss_idx_get(h, (int64_t)member, &sc);
    ss_rwlock_rdunlock(h);
    RETVAL = found ? newSVnv(sc) : &PL_sv_undef;
  OUTPUT:
    RETVAL

bool
exists(self, member)
    SV *self
    IV member
  PREINIT:
    EXTRACT(self);
    double sc;
  CODE:
    ss_rwlock_rdlock(h);
    RETVAL = ss_idx_get(h, (int64_t)member, &sc);
    ss_rwlock_rdunlock(h);
  OUTPUT:
    RETVAL

bool
remove(self, member)
    SV *self
    IV member
  PREINIT:
    EXTRACT(self);
  CODE:
    ss_rwlock_wrlock(h);
    RETVAL = ss_remove_locked(h, (int64_t)member);
    __atomic_fetch_add(&h->hdr->stat_ops, 1, __ATOMIC_RELAXED);
    ss_rwlock_wrunlock(h);
  OUTPUT:
    RETVAL

NV
incr(self, member, delta)
    SV *self
    IV member
    NV delta
  PREINIT:
    EXTRACT(self);
    double out;
    int rc;
  CODE:
    if (delta != delta) croak("incr: delta must not be NaN");
    ss_rwlock_wrlock(h);
    rc = ss_incr_locked(h, (int64_t)member, (double)delta, &out);
    __atomic_fetch_add(&h->hdr->stat_ops, 1, __ATOMIC_RELAXED);
    ss_rwlock_wrunlock(h);
    if (rc == -1) croak("incr: max_entries exhausted");
    if (rc == -2) croak("incr: result is NaN");
    RETVAL = out;
  OUTPUT:
    RETVAL

void
pop_min(self)
    SV *self
  PREINIT:
    EXTRACT(self);
  PPCODE:
    {
        int64_t m; double s; int ok;
        ss_rwlock_wrlock(h);
        ok = ss_pop_locked(h, 0, &m, &s);
        if (ok) __atomic_fetch_add(&h->hdr->stat_ops, 1, __ATOMIC_RELAXED);
        ss_rwlock_wrunlock(h);
        if (ok) { EXTEND(SP, 2); PUSHs(sv_2mortal(newSViv((IV)m))); PUSHs(sv_2mortal(newSVnv(s))); }
    }

void
pop_max(self)
    SV *self
  PREINIT:
    EXTRACT(self);
  PPCODE:
    {
        int64_t m; double s; int ok;
        ss_rwlock_wrlock(h);
        ok = ss_pop_locked(h, 1, &m, &s);
        if (ok) __atomic_fetch_add(&h->hdr->stat_ops, 1, __ATOMIC_RELAXED);
        ss_rwlock_wrunlock(h);
        if (ok) { EXTEND(SP, 2); PUSHs(sv_2mortal(newSViv((IV)m))); PUSHs(sv_2mortal(newSVnv(s))); }
    }

bool
_validate(self)
    SV *self
  PREINIT:
    EXTRACT(self);
  CODE:
    ss_rwlock_rdlock(h);
    RETVAL = ss_validate_tree(h);
    ss_rwlock_rdunlock(h);
  OUTPUT:
    RETVAL

SV *
rank(self, member)
    SV *self
    IV member
  PREINIT:
    EXTRACT(self);
    double sc;
  CODE:
    {
    UV rk = 0; int found;
    ss_rwlock_rdlock(h);
    found = ss_idx_get(h, (int64_t)member, &sc);
    if (found) rk = ss_rank_of(h, sc, (int64_t)member);
    ss_rwlock_rdunlock(h);
    RETVAL = found ? newSVuv(rk) : &PL_sv_undef;   /* build SV after unlock: an OOM in newSVuv must not strand the read lock */
    }
  OUTPUT:
    RETVAL

SV *
rev_rank(self, member)
    SV *self
    IV member
  PREINIT:
    EXTRACT(self);
    double sc;
  CODE:
    {
    UV rk = 0; int found;
    ss_rwlock_rdlock(h);
    found = ss_idx_get(h, (int64_t)member, &sc);
    if (found) rk = h->hdr->count - 1 - ss_rank_of(h, sc, (int64_t)member);
    ss_rwlock_rdunlock(h);
    RETVAL = found ? newSVuv(rk) : &PL_sv_undef;   /* build SV after unlock */
    }
  OUTPUT:
    RETVAL

SV *
at_rank(self, rank)
    SV *self
    IV rank
  PREINIT:
    EXTRACT(self);
  CODE:
    {
    IV val = 0; int found = 0;
    ss_rwlock_rdlock(h);
    {
        uint32_t cnt = h->hdr->count;
        IV r = rank; if (r < 0) r += (IV)cnt;
        if (r >= 0 && (uint64_t)r < cnt) {          /* compare in 64-bit; large r must not truncate to an in-range index */
            int pos; uint32_t leaf = ss_at_rank(h, (uint32_t)r, &pos);
            if (leaf != SS_NONE) { val = (IV)h->nodes[leaf].members[pos]; found = 1; }
        }
    }
    ss_rwlock_rdunlock(h);
    RETVAL = found ? newSViv(val) : &PL_sv_undef;   /* build SV after unlock */
    }
  OUTPUT:
    RETVAL

UV
count_in_score(self, min, max)
    SV *self
    NV min
    NV max
  PREINIT:
    EXTRACT(self);
  CODE:
    ss_rwlock_rdlock(h);
    RETVAL = ss_count_in_score(h, (double)min, (double)max, NULL);
    ss_rwlock_rdunlock(h);
  OUTPUT:
    RETVAL

void
range_by_rank(self, start, stop, ...)
    SV *self
    IV start
    IV stop
  PREINIT:
    EXTRACT(self);
  PPCODE:
    int ws = 0;
    ss_parse_range_opts(aTHX_ &ST(0), 3, items, &ws, NULL, NULL);
    REEXTRACT(self);
    ss_rwlock_rdlock(h);
    {
        uint32_t s0 = 0, len = 0;
        IV a, b;
        if (ss_rank_window(h->hdr->count, start, stop, &a, &b)) { s0 = (uint32_t)a; len = (uint32_t)(b - a + 1); }
        EMIT_COLLECTED(s0, len, 0, ws);
    }

void
rev_range_by_rank(self, start, stop, ...)
    SV *self
    IV start
    IV stop
  PREINIT:
    EXTRACT(self);
  PPCODE:
    int ws = 0;
    ss_parse_range_opts(aTHX_ &ST(0), 3, items, &ws, NULL, NULL);
    REEXTRACT(self);
    ss_rwlock_rdlock(h);
    {
        uint32_t cnt = h->hdr->count, s0 = 0, len = 0;
        IV a, b;
        if (ss_rank_window(cnt, start, stop, &a, &b)) { s0 = (uint32_t)((IV)cnt - 1 - b); len = (uint32_t)(b - a + 1); }
        EMIT_COLLECTED(s0, len, 1, ws);
    }

void
range_by_score(self, min, max, ...)
    SV *self
    NV min
    NV max
  PREINIT:
    EXTRACT(self);
  PPCODE:
    int ws = 0; IV limit = -1, offset = 0;
    ss_parse_range_opts(aTHX_ &ST(0), 3, items, &ws, &limit, &offset);
    REEXTRACT(self);
    ss_rwlock_rdlock(h);
    {
        uint32_t lo;
        uint32_t win = ss_count_in_score(h, (double)min, (double)max, &lo);
        uint32_t off = (offset > 0) ? (offset >= (IV)win ? win : (uint32_t)offset) : 0;
        uint32_t s0 = lo, len = 0;
        if (off < win) { s0 = lo + off; len = win - off; if (limit >= 0 && limit < (IV)len) len = (uint32_t)limit; }
        EMIT_COLLECTED(s0, len, 0, ws);
    }

void
rev_range_by_score(self, max, min, ...)
    SV *self
    NV max
    NV min
  PREINIT:
    EXTRACT(self);
  PPCODE:
    int ws = 0; IV limit = -1, offset = 0;
    ss_parse_range_opts(aTHX_ &ST(0), 3, items, &ws, &limit, &offset);
    REEXTRACT(self);
    ss_rwlock_rdlock(h);
    {
        uint32_t lo;
        uint32_t win = ss_count_in_score(h, (double)min, (double)max, &lo);
        uint32_t off = (offset > 0) ? (offset >= (IV)win ? win : (uint32_t)offset) : 0;
        uint32_t s0 = lo, len = 0;
        if (off < win) { len = win - off; if (limit >= 0 && limit < (IV)len) len = (uint32_t)limit;
                         s0 = lo + (win - off - len); }
        EMIT_COLLECTED(s0, len, 1, ws);
    }

void
peek_min(self)
    SV *self
  PREINIT:
    EXTRACT(self);
  PPCODE:
    ss_rwlock_rdlock(h);
    if (h->hdr->root != SS_NONE && ss_node_ok(h, h->hdr->leftmost)) {
        SsNode *nd = &h->nodes[h->hdr->leftmost];
        IV m = (IV)nd->members[0]; NV s = nd->scores[0];
        ss_rwlock_rdunlock(h);
        EXTEND(SP, 2);
        PUSHs(sv_2mortal(newSViv(m)));
        PUSHs(sv_2mortal(newSVnv(s)));
    } else ss_rwlock_rdunlock(h);

void
peek_max(self)
    SV *self
  PREINIT:
    EXTRACT(self);
  PPCODE:
    ss_rwlock_rdlock(h);
    if (h->hdr->root != SS_NONE && ss_node_ok(h, h->hdr->rightmost)) {
        SsNode *nd = &h->nodes[h->hdr->rightmost];
        IV m = (IV)nd->members[nd->num - 1]; NV s = nd->scores[nd->num - 1];
        ss_rwlock_rdunlock(h);
        EXTEND(SP, 2);
        PUSHs(sv_2mortal(newSViv(m)));
        PUSHs(sv_2mortal(newSVnv(s)));
    } else ss_rwlock_rdunlock(h);

void
each(self, cb)
    SV *self
    SV *cb
  PREINIT:
    EXTRACT(self);
  CODE:
    SvGETMAGIC(cb);   /* a tied/overloaded scalar may FETCH to a coderef */
    if (!SvROK(cb) || SvTYPE(SvRV(cb)) != SVt_PVCV) croak("each: callback must be a code ref");
    {
        ss_rcollect_t col = { NULL, NULL, 0, 0 };
        REEXTRACT(self);
        ss_rwlock_rdlock(h);
        int ok = ss_collect_range(h, 0, h->hdr->count, 0, &col);
        ss_rwlock_rdunlock(h);
        if (!ok) { free(col.members); free(col.scores); croak("each: out of memory"); }
        for (size_t i = 0; i < col.n; i++) {
            dSP; ENTER; SAVETMPS; PUSHMARK(SP);
            XPUSHs(sv_2mortal(newSViv((IV)col.members[i])));
            XPUSHs(sv_2mortal(newSVnv(col.scores[i])));
            PUTBACK;
            call_sv(cb, G_VOID|G_DISCARD|G_EVAL);
            FREETMPS; LEAVE;
            if (SvTRUE(ERRSV)) { free(col.members); free(col.scores); croak_sv(ERRSV); }
        }
        free(col.members); free(col.scores);
    }

SV *
path(self)
    SV *self
  PREINIT:
    EXTRACT(self);
  CODE:
    RETVAL = h->path ? newSVpv(h->path, 0) : &PL_sv_undef;
  OUTPUT:
    RETVAL

int
memfd(self)
    SV *self
  PREINIT:
    EXTRACT(self);
  CODE:
    RETVAL = h->backing_fd;
  OUTPUT:
    RETVAL

void
sync(self)



( run in 2.348 seconds using v1.01-cache-2.11-cpan-92ad3014f07 )