Data-Pool-Shared
view release on metacpan or search on metacpan
#define PERL_NO_GET_CONTEXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#include "pool.h"
/* slot_sv lifetime magic: returned scalar pins the pool object alive by
* holding an incremented refcount, released when the scalar is freed. */
static int pool_scalar_magic_free(pTHX_ SV *sv, MAGIC *mg) {
PERL_UNUSED_ARG(sv);
if (mg->mg_obj) SvREFCNT_dec(mg->mg_obj);
return 0;
}
static const MGVTBL pool_scalar_magic_vtbl = {
NULL, NULL, NULL, NULL, pool_scalar_magic_free, NULL, NULL, NULL
};
#define EXTRACT_POOL(sv) \
if (!sv_isobject(sv) || !sv_derived_from(sv, "Data::Pool::Shared")) \
croak("Expected a Data::Pool::Shared object"); \
PoolHandle *h = INT2PTR(PoolHandle*, SvIV(SvRV(sv))); \
if (!h) croak("Attempted to use a destroyed Data::Pool::Shared object")
#define MAKE_OBJ(class, handle) \
SV *obj = newSViv(PTR2IV(handle)); \
SV *ref = newRV_noinc(obj); \
sv_bless(ref, gv_stashpv(class, GV_ADD)); \
RETVAL = ref
#define CHECK_SLOT(h, slot) \
if ((UV)(slot) >= (h)->hdr->capacity) \
croak("slot %" UVuf " out of range (capacity %" UVuf ")", \
(UV)(slot), (UV)(h)->hdr->capacity)
#define CHECK_ALLOCATED(h, slot) \
if (!pool_is_allocated(h, slot)) \
croak("slot %" UVuf " is not allocated", (UV)(slot))
MODULE = Data::Pool::Shared PACKAGE = Data::Pool::Shared
PROTOTYPES: DISABLE
SV *
new(class, path, capacity, elem_size)
const char *class
SV *path
UV capacity
UV elem_size
PREINIT:
char errbuf[POOL_ERR_BUFLEN];
CODE:
const char *p = SvOK(path) ? SvPV_nolen(path) : NULL;
PoolHandle *h = pool_create(p, capacity, (uint32_t)elem_size, POOL_VAR_RAW, errbuf);
if (!h) croak("Data::Pool::Shared->new: %s", errbuf);
MAKE_OBJ(class, h);
OUTPUT:
RETVAL
SV *
new_memfd(class, name, capacity, elem_size)
const char *class
const char *name
UV capacity
UV elem_size
PREINIT:
allocated_slots(self)
SV *self
PREINIT:
EXTRACT_POOL(self);
CODE:
AV *av = newAV();
uint64_t cap = h->hdr->capacity;
uint32_t nwords = h->bitmap_words;
for (uint32_t widx = 0; widx < nwords; widx++) {
uint64_t word = __atomic_load_n(&h->bitmap[widx], __ATOMIC_RELAXED);
while (word) {
int bit = __builtin_ctzll(word);
uint64_t slot = (uint64_t)widx * 64 + bit;
if (slot < cap)
av_push(av, newSViv((IV)slot));
word &= word - 1;
}
}
RETVAL = newRV_noinc((SV *)av);
OUTPUT:
RETVAL
UV
ptr(self, slot)
SV *self
UV slot
PREINIT:
EXTRACT_POOL(self);
CODE:
CHECK_SLOT(h, slot);
CHECK_ALLOCATED(h, slot);
RETVAL = PTR2UV(pool_slot_ptr(h, slot));
OUTPUT:
RETVAL
UV
data_ptr(self)
SV *self
PREINIT:
EXTRACT_POOL(self);
CODE:
RETVAL = PTR2UV(h->data);
OUTPUT:
RETVAL
SV *
slot_sv(self, slot)
SV *self
UV slot
PREINIT:
EXTRACT_POOL(self);
CODE:
CHECK_SLOT(h, slot);
CHECK_ALLOCATED(h, slot);
RETVAL = newSV(0);
sv_upgrade(RETVAL, SVt_PV);
SvPV_set(RETVAL, (char *)pool_slot_ptr(h, slot));
SvLEN_set(RETVAL, 0);
SvCUR_set(RETVAL, h->hdr->elem_size);
SvPOK_on(RETVAL);
/* Pin pool alive while this SV is referenced â magic before READONLY */
MAGIC *mg = sv_magicext(RETVAL, NULL, PERL_MAGIC_ext, &pool_scalar_magic_vtbl, NULL, 0);
mg->mg_obj = SvREFCNT_inc_simple_NN(self);
SvREADONLY_on(RETVAL);
OUTPUT:
RETVAL
MODULE = Data::Pool::Shared PACKAGE = Data::Pool::Shared::I64
PROTOTYPES: DISABLE
SV *
new(class, path, capacity)
const char *class
SV *path
UV capacity
PREINIT:
char errbuf[POOL_ERR_BUFLEN];
CODE:
const char *p = SvOK(path) ? SvPV_nolen(path) : NULL;
PoolHandle *h = pool_create(p, capacity, sizeof(int64_t), POOL_VAR_I64, errbuf);
if (!h) croak("Data::Pool::Shared::I64->new: %s", errbuf);
MAKE_OBJ(class, h);
OUTPUT:
RETVAL
SV *
new_memfd(class, name, capacity)
const char *class
const char *name
UV capacity
PREINIT:
char errbuf[POOL_ERR_BUFLEN];
CODE:
PoolHandle *h = pool_create_memfd(name, capacity, sizeof(int64_t), POOL_VAR_I64, errbuf);
if (!h) croak("Data::Pool::Shared::I64->new_memfd: %s", errbuf);
MAKE_OBJ(class, h);
OUTPUT:
RETVAL
SV *
new_from_fd(class, fd)
const char *class
int fd
PREINIT:
char errbuf[POOL_ERR_BUFLEN];
CODE:
PoolHandle *h = pool_open_fd(fd, POOL_VAR_I64, errbuf);
if (!h) croak("Data::Pool::Shared::I64->new_from_fd: %s", errbuf);
MAKE_OBJ(class, h);
OUTPUT:
RETVAL
IV
get(self, slot)
SV *self
UV slot
PREINIT:
EXTRACT_POOL(self);
CODE:
( run in 0.558 second using v1.01-cache-2.11-cpan-39bf76dae61 )