Data-TimingWheel-Shared
view release on metacpan or search on metacpan
const char *class
int fd
PREINIT:
char errbuf[TW_ERR_BUFLEN];
CODE:
TwHandle *h = tw_open_fd(fd, errbuf);
if (!h) croak("Data::TimingWheel::Shared->new_from_fd: %s", errbuf);
MAKE_OBJ(class, h);
OUTPUT:
RETVAL
void
DESTROY(self)
SV *self
CODE:
if (sv_isobject(self) && sv_derived_from(self, "Data::TimingWheel::Shared")) {
TwHandle *h = INT2PTR(TwHandle*, SvIV(SvRV(self)));
if (h) { sv_setiv(SvRV(self), 0); tw_destroy(h); } /* null first: activates EXTRACT's use-after-destroy croak + makes a double DESTROY a no-op */
}
UV
add(self, delay, payload)
SV *self
IV delay
UV payload
PREINIT:
EXTRACT(self);
int64_t id;
CODE:
/* signed delay: a negative value (e.g. from clock skew) clamps to 1 tick per
* the POD, instead of UV-wrapping to a ~2^64 delay that never fires (slot leak) */
tw_rwlock_wrlock(h);
id = tw_add_locked(h, delay < 1 ? 1 : (uint64_t)delay, (uint64_t)payload);
__atomic_fetch_add(&h->hdr->stat_ops, 1, __ATOMIC_RELAXED);
tw_rwlock_wrunlock(h);
if (id < 0) croak("Data::TimingWheel::Shared->add: timer pool is full (capacity %u)", (unsigned)h->capacity);
RETVAL = (UV)id;
OUTPUT:
RETVAL
int
cancel(self, timer_id)
SV *self
UV timer_id
PREINIT:
EXTRACT(self);
CODE:
tw_rwlock_wrlock(h);
RETVAL = tw_cancel_locked(h, (uint64_t)timer_id);
__atomic_fetch_add(&h->hdr->stat_ops, 1, __ATOMIC_RELAXED);
tw_rwlock_wrunlock(h);
OUTPUT:
RETVAL
void
advance(self, ticks = 1)
SV *self
IV ticks
PREINIT:
EXTRACT(self);
PPCODE:
{
REEXTRACT(self); /* `ticks = 1` is converted after PREINIT, so its magic already ran */
uint64_t *out = NULL, fired = 0, i, cap = h->capacity;
/* signed: reject a negative tick count (would UV-wrap to ~2^64 and spin the
* per-tick loop under the write lock, wedging every sharer) */
if (ticks < 0) croak("Data::TimingWheel::Shared->advance: ticks must be >= 0");
if (cap) { Newx(out, (size_t)cap, uint64_t); SAVEFREEPV(out); } /* alloc BEFORE the lock */
tw_rwlock_wrlock(h);
fired = cap ? tw_advance_locked(h, (uint64_t)ticks, out, cap) : 0;
__atomic_fetch_add(&h->hdr->stat_ops, 1, __ATOMIC_RELAXED);
tw_rwlock_wrunlock(h);
EXTEND(SP, (SSize_t)fired);
for (i = 0; i < fired; i++) PUSHs(sv_2mortal(newSVuv((UV)out[i]))); /* Perl alloc AFTER unlock */
}
UV
now(self)
SV *self
PREINIT:
EXTRACT(self);
UV v;
CODE:
tw_rwlock_rdlock(h);
v = (UV)h->hdr->now;
tw_rwlock_rdunlock(h);
RETVAL = v;
OUTPUT:
RETVAL
UV
count(self)
SV *self
PREINIT:
EXTRACT(self);
UV v;
CODE:
tw_rwlock_rdlock(h);
v = (UV)h->hdr->count;
tw_rwlock_rdunlock(h);
RETVAL = v;
OUTPUT:
RETVAL
UV
capacity(self)
SV *self
PREINIT:
EXTRACT(self);
CODE:
RETVAL = (UV)h->hdr->capacity;
OUTPUT:
RETVAL
UV
num_slots(self)
SV *self
PREINIT:
EXTRACT(self);
CODE:
RETVAL = (UV)h->hdr->num_slots;
( run in 1.578 second using v1.01-cache-2.11-cpan-92ad3014f07 )