Ancient
view release on metacpan or search on metacpan
xs/doubly/doubly.c view on Meta::CPAN
#ifdef USE_ITHREADS
owner_tid_sv = hv_fetch(hash, "_owner_tid", 10, 0);
owner_tid = owner_tid_sv ? SvUV(*owner_tid_sv) : PTR2UV(PERL_GET_THX);
#endif
list_incref(list_idx);
#ifdef USE_ITHREADS
ST(0) = sv_2mortal(create_doubly_object(aTHX_ list_idx, new_node_id, owner_tid));
#else
ST(0) = sv_2mortal(create_doubly_object(aTHX_ list_idx, new_node_id));
#endif
XSRETURN(1);
}
static XS(xs_find) {
dXSARGS;
HV* hash;
SV** id_sv;
IV list_idx;
SV* cb;
DoublyListMeta* list;
DoublyNodeSlot* node;
IV node_idx;
SV* node_data;
int found;
IV found_node_id;
IV current_node_id;
#ifdef USE_ITHREADS
SV** owner_tid_sv;
UV owner_tid;
#endif
if (items < 2) croak("Usage: doubly::find(self, callback)");
hash = (HV*)SvRV(ST(0));
id_sv = hv_fetch(hash, "_id", 3, 0);
list_idx = id_sv ? SvIV(*id_sv) : -1;
cb = ST(1);
found = 0;
found_node_id = 0;
DOUBLY_LOCK();
list = get_list(list_idx);
if (list && !list->destroyed && list->length > 0) {
node_idx = list->head_idx;
while (node_idx >= 0 && !found) {
node = get_node(node_idx);
if (!node) break;
current_node_id = node->node_id;
node_data = node->data ? newSVsv(node->data) : &PL_sv_undef;
DOUBLY_UNLOCK();
{
dSP;
PUSHMARK(SP);
XPUSHs(sv_2mortal(node_data));
PUTBACK;
call_sv(cb, G_SCALAR);
SPAGAIN;
if (SvTRUE(*PL_stack_sp)) {
found = 1;
found_node_id = current_node_id;
}
POPs;
}
DOUBLY_LOCK();
list = get_list(list_idx);
if (!list || list->destroyed) break;
if (!found) {
/* Re-find node by ID since list may have changed during callback */
node_idx = find_node_by_id(list, current_node_id);
if (node_idx >= 0) {
node = get_node(node_idx);
if (node) {
node_idx = node->next_idx;
} else {
break;
}
} else {
/* Node was removed during callback, try to continue from head */
break;
}
}
}
}
DOUBLY_UNLOCK();
if (found) {
#ifdef USE_ITHREADS
owner_tid_sv = hv_fetch(hash, "_owner_tid", 10, 0);
owner_tid = owner_tid_sv ? SvUV(*owner_tid_sv) : PTR2UV(PERL_GET_THX);
#endif
list_incref(list_idx);
#ifdef USE_ITHREADS
ST(0) = sv_2mortal(create_doubly_object(aTHX_ list_idx, found_node_id, owner_tid));
#else
ST(0) = sv_2mortal(create_doubly_object(aTHX_ list_idx, found_node_id));
#endif
} else {
ST(0) = &PL_sv_undef;
}
XSRETURN(1);
}
static XS(xs_insert) {
dXSARGS;
HV* hash;
SV** id_sv;
IV list_idx;
SV* cb;
SV* data;
DoublyListMeta* list;
DoublyNodeSlot* node;
IV node_idx;
IV current_node_id;
SV* node_data;
int found;
IV pos;
if (items < 3 || !SvROK(ST(0)) || SvTYPE(SvRV(ST(0))) != SVt_PVHV)
croak("Usage: doubly::insert(self, callback, data)");
hash = (HV*)SvRV(ST(0));
id_sv = hv_fetch(hash, "_id", 3, 0);
list_idx = id_sv ? SvIV(*id_sv) : -1;
cb = ST(1);
data = ST(2);
found = 0;
pos = 0;
DOUBLY_LOCK();
list = get_list(list_idx);
if (list && !list->destroyed && list->length > 0) {
node_idx = list->head_idx;
while (node_idx >= 0 && !found) {
node = get_node(node_idx);
if (!node) break;
current_node_id = node->node_id;
node_data = node->data ? newSVsv(node->data) : &PL_sv_undef;
DOUBLY_UNLOCK();
{
dSP;
PUSHMARK(SP);
XPUSHs(sv_2mortal(node_data));
PUTBACK;
call_sv(cb, G_SCALAR);
SPAGAIN;
if (SvTRUE(*PL_stack_sp)) {
found = 1;
}
POPs;
}
DOUBLY_LOCK();
list = get_list(list_idx);
if (!list || list->destroyed) break;
if (!found) {
/* Re-find node by ID since list may have changed during callback */
node_idx = find_node_by_id(list, current_node_id);
if (node_idx >= 0) {
node = get_node(node_idx);
if (node) {
node_idx = node->next_idx;
pos++;
} else {
break;
}
} else {
/* Node was removed during callback */
break;
}
}
}
}
DOUBLY_UNLOCK();
if (found) {
list_insert_at_pos(aTHX_ list_idx, pos, data);
} else {
list_add(aTHX_ list_idx, data);
}
/* Return $self for chaining - no refcount increment needed */
XSRETURN(1);
}
static XS(xs_destroy) {
dXSARGS;
HV* hash;
SV** id_sv;
IV list_idx;
if (items < 1) croak("Usage: doubly::destroy(self)");
hash = (HV*)SvRV(ST(0));
id_sv = hv_fetch(hash, "_id", 3, 0);
list_idx = id_sv ? SvIV(*id_sv) : -1;
list_destroy(aTHX_ list_idx);
XSRETURN_EMPTY;
}
static XS(xs_DESTROY) {
dXSARGS;
( run in 0.453 second using v1.01-cache-2.11-cpan-13bb782fe5a )