/**************************************************************************** ** *FGROW_WPOBJ(<wp>,<need>)...ensureweakpointerobjectislargeenough ** **'GROW_WPOBJ'growstheweakpointerobject<wp>ifnecessarytoensure **thatithasroomforatleast<need>elements.
*/ staticinlinevoid GROW_WPOBJ(Obj wp, UInt need)
{
UInt plen; // new physical length
UInt good; // good new physical length
// if there is already enough space, do nothing if (need < SIZE_OBJ(wp)/sizeof(Obj)) return;
if (need > INT_INTOBJ_MAX)
ErrorMayQuit("GrowWPObj: List size too large", 0, 0);
// find out how large the object should become at least (we grow by // at least 25%, like plain lists) // find out how large the plain list should become
good = 5 * (SIZE_OBJ(wp)/sizeof(Obj)-1) / 4 + 4;
// but maybe we need more if ( need < good ) { plen = good; } else { plen = need; }
static Obj FuncWeakPointerObj(Obj self, Obj list)
{
Obj wp; Int i; Int len; #ifdef USE_BOEHM_GC // We need to make sure that the list stays live until // after REGISTER_WP(); on architectures that pass // arguments in registers (x86_64, SPARC, etc), the // argument register may be reused. In conjunction with // loop unrolling, the reference to 'list' may then be // destroyed before REGISTER_WP() is called. volatile Obj list2 = list; #endif
len = LEN_LIST(list); if (len > INT_INTOBJ_MAX)
ErrorMayQuit("WeakPointerObj: List size too large", 0, 0);
wp = (Obj) NewBag(T_WPOBJ, (len+1)*sizeof(Obj));
STORE_LEN_WPOBJ(wp,len); for (i = 1; i <= len ; i++)
{ #ifdef USE_BOEHM_GC
Obj tmp = ELM0_LIST(list2, i);
SET_ELM_WPOBJ(wp, i, tmp); if (IS_BAG_REF(tmp))
REGISTER_WP(wp, i, tmp); #else
SET_ELM_WPOBJ(wp, i, ELM0_LIST(list, i)); #endif // this must be here in case list is in fact an object and causes a GC // in the element access method
CHANGED_BAG(wp);
}
Int len = LengthWPObj(wp); if ( ipos <= len ) { #ifdef USE_BOEHM_GC // Ensure the result is visible on the stack in case a garbage // collection happens after the read. volatile Obj tmp = ELM_WPOBJ(wp, ipos); #ifdef HPCGAP
MEMBAR_READ(); #endif if (ELM_WPOBJ(wp, ipos)) { if (IS_BAG_REF(tmp))
FORGET_WP(wp, ipos);
SET_ELM_WPOBJ(wp, ipos, 0);
} #else
SET_ELM_WPOBJ(wp, ipos, 0); #endif
} return0;
}
staticvoid MarkWeakPointerObj(Obj wp, void * ref)
{ // can't use the stored length here, in case we are in the middle of // copying const UInt len = SIZE_BAG(wp) / sizeof(Obj) - 1; for (UInt i = 1; i <= len; i++) {
MarkBagWeakly(CONST_ADDR_OBJ(wp)[i]);
}
}
staticvoid SweepWeakPointerObj( Bag *src, Bag *dst, UInt len)
{
Bag elm; while (len --)
{
elm = *src++;
*dst ++ = IsWeakDeadBag(elm) ? (Bag) 0 : elm;
}
}
#endif
#ifdef USE_JULIA_GC
staticvoid MarkWeakPointerObj(Obj wp, void * ref)
{ // can't use the stored length here, in case we are in the middle of // copying const UInt len = SIZE_BAG(wp) / sizeof(Obj) - 1; for (UInt i = 1; i <= len; i++) {
Bag elm = CONST_ADDR_OBJ(wp)[i]; if (IS_BAG_REF(elm))
MarkJuliaWeakRef(elm, ref);
}
}
// immutable input is handled by COPY_OBJ
GAP_ASSERT(IS_MUTABLE_OBJ(obj));
// This may get smaller if a GC occurs during copying
UInt len = LengthWPObj(obj);
// make a copy if ( mut ) {
copy = NewBag( T_WPOBJ, SIZE_OBJ(obj) );
ADDR_OBJ(copy)[0] = CONST_ADDR_OBJ(obj)[0];
} else {
copy = NEW_PLIST_IMM(T_PLIST, len); // Set length as plist is constructed
}
// leave a forwarding pointer
PrepareCopy(obj, copy);
// copy the subvalues. Loop goes up so length of PLIST is set correctly for (i = 1; i <= len; i++) {
elm = ELM_WPOBJ(obj, i); if (elm) {
tmp = COPY_OBJ(elm, mut); if (mut)
SET_ELM_WPOBJ(copy, i, tmp); else {
SET_ELM_PLIST(copy, i, tmp);
SET_LEN_PLIST(copy, i);
}
CHANGED_BAG( copy );
}
}
staticvoid MakeImmutableWPObj(Obj obj)
{ #ifdef USE_BOEHM_GC
UInt i;
UInt len = 0;
Obj copy = NEW_PLIST(T_PLIST, STORED_LEN_WPOBJ(obj)); for (i = 1; i <= STORED_LEN_WPOBJ(obj); i++) { #ifdef HPCGAP volatile Obj tmp = ELM_WPOBJ(obj, i);
MEMBAR_READ(); if (tmp) { if (IS_BAG_REF(tmp) && ELM_WPOBJ(obj, i)) {
FORGET_WP(obj, i);
}
len = i;
} #else
Obj tmp = ELM_WPOBJ(obj, i); if (tmp) { if (IS_BAG_REF(tmp)) {
FORGET_WP(obj, i);
}
len = i;
} #endif
SET_ELM_PLIST(copy, i, tmp);
}
SET_LEN_PLIST(copy, len);
SET_PTR_BAG(obj, PTR_BAG(copy));
// Note: there is brief moment here where the WP obj has been turned into a // mutable plist, but not yet been made immutable. This should be fine as // long as the object is non-public, i.e., owned exclusively by the current // thread.
#else // recompute stored length
UInt len = LengthWPObj(obj);
// remove any weak dead bags, by relying on side-effect of ELM_WPOBJ for (UInt i = 1; i <= len; i++) { #ifdef USE_JULIA_GC
Obj elm = ELM_WPOBJ(obj, i); if (IS_BAG_REF(elm)) { // write back the entries using ADDR_OBJ (not SET_ELM_WPOBJ) to // get rid of the jl_weakref_t objects
ADDR_OBJ(obj)[i] = elm;
} #else
ELM_WPOBJ(obj, i); #endif
}
// change the type - this works correctly, as the layout of weak pointer // objects and plists is identical, and we removed all weak dead bags, // and set the length properly.
RetypeBag(obj, (len == 0) ? T_PLIST_EMPTY : T_PLIST); #endif
// make the plist immutable (and recursively any subobjects); note that // this can cause garbage collections, hence we must do it after we // completed conversion of the WP object into a plist
MakeImmutable(obj);
}
/**************************************************************************** ** *FInitInfoWeakPtr()................tableofinitfunctions
*/ static StructInitInfo module = { // init struct using C99 designated initializers; for a full list of // fields, please refer to the definition of StructInitInfo
.type = MODULE_BUILTIN,
.name = "weakptr",
.initKernel = InitKernel,
.initLibrary = InitLibrary,
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.