Affix
view release on metacpan or search on metacpan
lib/Affix.c view on Meta::CPAN
ST(0) = sv_2mortal(rv);
}
else if (elem_type->category == INFIX_TYPE_ARRAY) {
// Return a new Affix::Pointer for this sub-array (Live view)
Affix_Pin * new_pin;
Newxz(new_pin, 1, Affix_Pin);
new_pin->pointer = target;
new_pin->managed = false;
new_pin->owner_sv = pin->owner_sv ? pin->owner_sv : ST(0);
SvREFCNT_inc(new_pin->owner_sv);
// We need to keep the type info alive. For now, copy it.
new_pin->type_arena = infix_arena_create(256);
new_pin->type = _copy_type_graph_to_arena(new_pin->type_arena, elem_type);
ST(0) = sv_2mortal(_new_pointer_obj(aTHX_ new_pin));
}
else {
SV * res = sv_newmortal();
ptr2sv(aTHX_ nullptr, target, res, elem_type);
ST(0) = res;
}
XSRETURN(1);
}
XS_INTERNAL(Affix_pin_set_at) {
dXSARGS;
if (items != 3)
croak_xs_usage(cv, "pin, index, value");
Affix_Pin * pin = _get_pin_from_sv(aTHX_ ST(0));
IV index = SvIV(ST(1));
SV * val_sv = ST(2);
if (!pin || !pin->type)
croak("Not a valid pinned pointer");
const infix_type * type = pin->type;
const infix_type * elem_type = type;
if (type->category == INFIX_TYPE_ARRAY)
elem_type = type->meta.array_info.element_type;
else if (type->category == INFIX_TYPE_POINTER && type->meta.pointer_info.pointee_type->category == INFIX_TYPE_VOID)
elem_type = type->meta.pointer_info.pointee_type;
else
croak("Cannot index into non-aggregate type");
size_t elem_size = infix_type_get_size(elem_type);
if (elem_size == 0 && elem_type->category == INFIX_TYPE_VOID) {
elem_size = 1;
elem_type = infix_type_create_primitive(INFIX_PRIMITIVE_UINT8);
}
if (elem_size == 0)
croak("Cannot index into zero-sized type");
void * target = (char *)pin->pointer + (index * elem_size);
sv2ptr(aTHX_ nullptr, val_sv, target, elem_type);
XSRETURN_EMPTY;
}
// Helper to register core internal types
static void _register_core_types(infix_registry_t * registry) {
// Register SV as a named type (dummy struct ensures it keeps the name in the registry).
// This allows signature parsing of "@SV" or "SV" (via hack) to map to a named opaque type.
// Direct usage of this type is blocked in get_opcode_for_type; it must be wrapped in Pointer[].
if (infix_register_types(registry, "@SV = { __sv_opaque: uint8 };") != INFIX_SUCCESS)
croak("Failed to register internal type alias '@SV'");
// We register File and PerlIO as opaque structs.
// This semantically matches C's FILE struct which (for now) will remain opaque to the user.
// We require "Pointer[File]" to mean "FILE*"
if (infix_register_types(registry, "@File = { _opaque: [0:uchar] };") != INFIX_SUCCESS)
croak("Failed to register internal type alias '@File'");
if (infix_register_types(registry, "@PerlIO = { _opaque: [0:uchar] };") != INFIX_SUCCESS)
croak("Failed to register internal type alias '@PerlIO'");
// Other special types are opaque structs too. ...but they don't always mean anything in particular.
if (infix_register_types(registry, "@StringList = *void;") != INFIX_SUCCESS)
croak("Failed to register internal type alias '@StringList'");
if (infix_register_types(registry, "@Buffer = *void;") != INFIX_SUCCESS)
croak("Failed to register internal type alias '@Buffer'");
if (infix_register_types(registry, "@SockAddr = *void;") != INFIX_SUCCESS)
croak("Failed to register internal type alias '@SockAddr'");
}
XS_INTERNAL(Affix_CLONE) {
dXSARGS;
PERL_UNUSED_VAR(items);
// Initialize the new thread's context (copies bitwise from parent)
MY_CXT_CLONE;
// Capture the parent's registry pointer.
// After MY_CXT_CLONE, MY_CXT refers to the new thread's context,
// which has been initialized as a bitwise copy of the parent's context.
infix_registry_t * parent_registry = MY_CXT.registry;
// Overwrite shared pointers with fresh objects for the new thread
MY_CXT.lib_registry = newHV();
MY_CXT.callback_registry = newHV();
MY_CXT.enum_registry = newHV();
MY_CXT.coercion_cache = newHV();
MY_CXT.stash_pointer = nullptr;
// Deep copy the type registry.
// This ensures typedefs and structs defined in the parent thread exist in the child thread,
// but the child owns its own memory arena, making it thread-safe.
if (parent_registry)
MY_CXT.registry = infix_registry_clone(parent_registry);
else
MY_CXT.registry = infix_registry_create();
if (!MY_CXT.registry)
warn("Failed to initialize the global type registry in new thread");
// Don't ccall _register_core_types here if we cloned, because the clone already contains @SV, @File, etc.
if (!parent_registry)
_register_core_types(MY_CXT.registry);
XSRETURN_EMPTY;
}
void boot_Affix(pTHX_ CV * cv) {
dVAR;
dXSBOOTARGSXSAPIVERCHK;
( run in 2.634 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )