Data-IntervalTree-Shared
view release on metacpan or search on metacpan
CODE:
ItHandle *h = it_open_fd(fd, errbuf);
if (!h) croak("Data::IntervalTree::Shared->new_from_fd: %s", errbuf);
class = SvPV_nolen(ST(0)); /* re-read after argument magic; see new() */
MAKE_OBJ(class, h);
OUTPUT:
RETVAL
void
DESTROY(self)
SV *self
CODE:
if (sv_isobject(self) && sv_derived_from(self, "Data::IntervalTree::Shared")) {
ItHandle *h = INT2PTR(ItHandle*, SvIV(SvRV(self)));
if (h) { sv_setiv(SvRV(self), 0); it_destroy(h); } /* null first: activates EXTRACT's use-after-destroy croak + makes a double DESTROY a no-op */
}
UV
add(self, lo, hi, id = &PL_sv_undef)
SV *self
IV lo
IV hi
SV *id
PREINIT:
EXTRACT(self);
int64_t slot;
uint64_t payload;
CODE:
if (lo > hi) croak("Data::IntervalTree::Shared->add: lo (%" IVdf ") > hi (%" IVdf ")", (IV)lo, (IV)hi);
/* resolve the id BEFORE locking: SvUV on a tied/overloaded SV can run Perl
* code that dies, and a longjmp past the wrlock would strand it on a live PID. */
int have_id = (SvGETMAGIC(id), SvOK(id));
uint64_t id_val = have_id ? (uint64_t)SvUV(id) : 0;
REEXTRACT(self);
it_rwlock_wrlock(h);
payload = have_id ? id_val : h->hdr->count; /* default id = insertion index */
slot = it_add_locked(h, (int64_t)lo, (int64_t)hi, payload);
__atomic_fetch_add(&h->hdr->stat_ops, 1, __ATOMIC_RELAXED);
it_rwlock_wrunlock(h);
if (slot < 0) croak("Data::IntervalTree::Shared->add: tree is full (capacity %u)", (unsigned)h->capacity);
RETVAL = (UV)slot;
OUTPUT:
RETVAL
void
build(self)
SV *self
PREINIT:
EXTRACT(self);
CODE:
it_rwlock_wrlock(h);
if (h->hdr->dirty) it_build_locked(h);
it_rwlock_wrunlock(h);
void
stab(self, point)
SV *self
IV point
PREINIT:
EXTRACT(self);
PPCODE:
{
ItRes *res = NULL;
uint64_t got = 0, cap = h->capacity;
if (cap) { Newx(res, (size_t)cap, ItRes); SAVEFREEPV(res); } /* alloc BEFORE the lock */
{
int wr = it_query_lock(h);
got = cap ? it_overlaps_locked(h, (int64_t)point, (int64_t)point, res, cap) : 0;
it_query_unlock(h, wr);
}
PUSH_RESULTS(res, got);
}
void
overlaps(self, lo, hi)
SV *self
IV lo
IV hi
PREINIT:
EXTRACT(self);
PPCODE:
{
ItRes *res = NULL;
uint64_t got = 0, cap = h->capacity;
if (lo > hi) croak("Data::IntervalTree::Shared->overlaps: lo (%" IVdf ") > hi (%" IVdf ")", (IV)lo, (IV)hi);
if (cap) { Newx(res, (size_t)cap, ItRes); SAVEFREEPV(res); } /* alloc BEFORE the lock */
{
int wr = it_query_lock(h);
got = cap ? it_overlaps_locked(h, (int64_t)lo, (int64_t)hi, res, cap) : 0;
it_query_unlock(h, wr);
}
PUSH_RESULTS(res, got);
}
void
clear(self)
SV *self
PREINIT:
EXTRACT(self);
CODE:
it_rwlock_wrlock(h);
it_clear_locked(h);
__atomic_fetch_add(&h->hdr->stat_ops, 1, __ATOMIC_RELAXED);
it_rwlock_wrunlock(h);
UV
count(self)
SV *self
PREINIT:
EXTRACT(self);
UV n;
CODE:
it_rwlock_rdlock(h);
n = (UV)h->hdr->count;
it_rwlock_rdunlock(h);
RETVAL = n;
OUTPUT:
RETVAL
UV
capacity(self)
SV *self
PREINIT:
EXTRACT(self);
CODE:
RETVAL = (UV)h->hdr->capacity;
OUTPUT:
RETVAL
SV *
stats(self)
SV *self
PREINIT:
EXTRACT(self);
CODE:
{
uint64_t count, ops;
uint32_t cap, dirty;
it_rwlock_rdlock(h);
count = h->hdr->count;
cap = h->hdr->capacity;
( run in 1.281 second using v1.01-cache-2.11-cpan-92ad3014f07 )