Data-SortedSet-Shared
view release on metacpan or search on metacpan
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 )