Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/GAP/src/   (Algebra von RWTH Aachen Version 4.15.1©)  Datei vom 18.9.2025 mit Größe 24 kB image not shown  

Quelle  weakptr.c   Sprache: C

 
/****************************************************************************
**
**  This file is part of GAP, a system for computational discrete algebra.
**
**  Copyright of GAP belongs to its developers, whose names are too numerous
**  to list here. Please refer to the COPYRIGHT file for details.
**
**  SPDX-License-Identifier: GPL-2.0-or-later
**
**  This file contains the functions that deal with weak pointer objects.
**  A weak pointer object looks like a plain list, except that its entries
**  are NOT kept alive through a garbage collection (unless they are contained
**  in some other kind of object).
*/


#include "weakptr.h"

#include "bool.h"
#include "error.h"
#ifdef USE_GASMAN
#include "gasman_intern.h"
#endif
#include "lists.h"
#include "modules.h"
#include "plist.h"
#include "saveload.h"

#ifdef HPCGAP
#include "hpc/guards.h"
#include "hpc/traverse.h"
#endif

#ifdef USE_BOEHM_GC
ifdef HPCGAP
#  define GC_THREADS
endif
include <gc/gc.h>
#endif

#ifdef USE_JULIA_GC
#include "julia.h"
#include "julia_gc.h"
#endif

#define RequireWPObj(funcname, op)                                           \
    RequireArgumentCondition(funcname, op, TNUM_OBJ(op) == T_WPOBJ,          \
                             "must be a weak pointer object")


/****************************************************************************
**
*F
*/


#if defined(USE_BOEHM_GC)

static inline void REGISTER_WP(Obj wp, UInt pos, Obj obj)
{
    void ** ptr = (void **)(ADDR_OBJ(wp) + pos);
    GC_general_register_disappearing_link(ptr, obj);
}

static inline void FORGET_WP(Obj wp, UInt pos)
{
    void ** ptr = (void **)(ADDR_OBJ(wp) + pos);
    GC_unregister_disappearing_link(ptr);
}

#endif


/****************************************************************************
**
*F  STORE_LEN_WPOBJ(<wp>,<len>) . . . . . . . . set the length of a WP object
**
**  'STORE_LEN_WPOBJ' sets the length of the WP object <wp> to <len>.
**
**  Objects at the end of <wp> may evaporate, so the stored length can only
**  be regarded as an upper bound.
*/

static inline void STORE_LEN_WPOBJ(Obj wp, Int len)
{
    ADDR_OBJ(wp)[0] = INTOBJ_INT(len);
}


/****************************************************************************
**
*F  STORED_LEN_WPOBJ(<wp>) . . . . . . . . . . . stored length of a WP object
**
**  'STORED_LEN_WPOBJ' returns the stored length of the WP object <wp>
**  as a C integer.
**
**  Note that as the list can mutate under your feet, the length may be
**  an overestimate.
*/

static inline Int STORED_LEN_WPOBJ(Obj wp)
{
    return INT_INTOBJ(CONST_ADDR_OBJ(wp)[0]);
}


/****************************************************************************
**
*F  ELM_WPOBJ(<wp>,<pos>) . . . . . . . . . . . . .  get entry of a WP object
**
**  'ELM_WPOBJ' return the <pos>-th element of the WP object <wp>. <pos> must
**  be a positive integer less than or equal  to the physical length of <wp>.
**  If <wp> has no assigned element at position <pos>, 'ELM_WPOBJ' returns 0.
*/

static inline Obj ELM_WPOBJ(Obj list, UInt pos)
{
    Bag elm = CONST_ADDR_OBJ(list)[pos];

#ifdef USE_GASMAN
    if (IsWeakDeadBag(elm)) {
        ADDR_OBJ(list)[pos] = 0;
        return 0;
    }
#endif

#ifdef USE_JULIA_GC
    if (!IS_BAG_REF(elm))
        return elm;
    jl_weakref_t * wref = (jl_weakref_t *)elm;
    if (wref->value == jl_nothing) {
        ADDR_OBJ(list)[pos] = 0;
        return 0;
    }
    elm = (Obj)(wref->value);
#endif

    return elm;
}


/****************************************************************************
**
*F  SET_ELM_WPOBJ(<wp>,<pos>,<val>) . . . . . . . .  set entry of a WP object
**
**  'SET_ELM_WPOBJ' sets the <pos>-th element of the WP object <wp> to <val>.
*/

static inline void SET_ELM_WPOBJ(Obj list, UInt pos, Obj val)
{
#ifndef USE_JULIA_GC
    ADDR_OBJ(list)[pos] = val;
#else
    Obj * ptr = ADDR_OBJ(list);
    if (!IS_BAG_REF(val)) {
        ptr[pos] = val;
        return;
    }
    if (!IS_BAG_REF(ptr[pos])) {
        ptr[pos] = (Bag)jl_gc_new_weakref((jl_value_t *)val);
        jl_gc_wb_back(BAG_HEADER(list));
    }
    else {
        jl_weakref_t * wref = (jl_weakref_t *)(ptr[pos]);
        wref->value = (jl_value_t *)val;
        jl_gc_wb(wref, BAG_HEADER(val));
    }
#endif
}


/****************************************************************************
**
*F  GROW_WPOBJ(<wp>,<need>) . . .  ensure weak pointer object is large enough
**
**  'GROW_WPOBJ' grows the weak pointer object <wp> if necessary to ensure
**  that it has room for at least <need> elements.
*/

static inline void 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; }

    if (plen > INT_INTOBJ_MAX)
        plen = INT_INTOBJ_MAX;

#if defined(USE_BOEHM_GC) && defined(HPCGAP)
    Obj copy = NewBag(T_WPOBJ, (plen+1) * sizeof(Obj));
    STORE_LEN_WPOBJ(copy, STORED_LEN_WPOBJ(wp));

    UInt i;
    for (i = 1; i <= STORED_LEN_WPOBJ(wp); i++) {
      volatile Obj tmp = ELM_WPOBJ(wp, i);
      MEMBAR_READ();
      if (IS_BAG_REF(tmp) && ELM_WPOBJ(wp, i)) {
        FORGET_WP(wp, i);
        REGISTER_WP(copy, i, tmp);
      }
      SET_ELM_WPOBJ(wp, i, 0);
      SET_ELM_WPOBJ(copy, i, tmp);
    }
    SET_PTR_BAG(wp, PTR_BAG(copy));
#else
    // resize the weak pointer object
    ResizeBag( wp, ((plen)+1)*sizeof(Obj) );
#endif
}


/****************************************************************************
**
*F  FuncWeakPointerObj(<self>,<list>) . . . . . .  make a weak pointer object
**
**  Handler for the GAP function WeakPointerObject(<list>), which makes a new
**  WP object.
*/


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);
    }

  return wp;
}


/****************************************************************************
**
*F  LengthWPObj(<wp>) . . . . . . . . . . . . . . current length of WP object
**
**  'LengthWPObj' returns the length of the WP object <wp> as a C integer.
**  The value cannot be trusted past a garbage collection, as trailing items
**  may evaporate.
**
**  Any identifiers of trailing objects that have evaporated in a garbage
**  collection are cleaned up by this function. However, for HPC-GAP, this
**  only happens if we have exclusive write access.
*/


static Int LengthWPObj(Obj wp)
{
  Int changed = 0;
  Int len = STORED_LEN_WPOBJ(wp);
#ifdef HPCGAP
  if (!CheckExclusiveWriteAccess(wp))
    return len;
#endif

  Obj elm;
  while (len > 0) {
    elm = ELM_WPOBJ(wp, len);
    if (elm)
        break;
    changed = 1;
    len--;
  }
  if (changed)
    STORE_LEN_WPOBJ(wp,len);
  return len;
}

/****************************************************************************
**
*F  FuncLengthWPObj(<wp>) . . . . . . . . . . . . current length of WP object
**
**  'FuncLengthWPObj' is a handler for a GAP function that returns the length
**  of the WP object <wp>. The value cannot be trusted past a garbage
**  collection, as trailing items may evaporate.
*/


static Obj FuncLengthWPObj(Obj self, Obj wp)
{
    RequireWPObj(SELF_NAME, wp);
    return INTOBJ_INT(LengthWPObj(wp));
}


/****************************************************************************
**
*F  FuncSetElmWPObj(<self>,<wp>,<pos>,<obj>) . .  set an entry in a WP object
**
**  'FuncSetElmWPObj'  is a handler for a GAP function that sets an entry in
**  a WP object.
*/


static Obj FuncSetElmWPObj(Obj self, Obj wp, Obj pos, Obj val)
{
    RequireWPObj(SELF_NAME, wp);
    UInt ipos = GetPositiveSmallInt(SELF_NAME, pos);

#ifdef USE_BOEHM_GC
  // Ensure reference remains visible to GC in case val is
  // stored in a register and the register is reused before
  // REGISTER_WP() is called.
  volatile Obj val2 = val;
#endif
  if (LengthWPObj(wp)  < ipos)
    {
      GROW_WPOBJ(wp, ipos);
      STORE_LEN_WPOBJ(wp,ipos);
    }
#ifdef USE_BOEHM_GC
  volatile Obj tmp = ELM_WPOBJ(wp, ipos);
#ifdef HPCGAP
  MEMBAR_READ();
#endif
  if (IS_BAG_REF(tmp) && ELM_WPOBJ(wp, ipos))
    FORGET_WP(wp, ipos);
  SET_ELM_WPOBJ(wp, ipos, val2);
  if (IS_BAG_REF(val2))
    REGISTER_WP(wp, ipos, val2);
#else
  SET_ELM_WPOBJ(wp, ipos, val);
#endif
  CHANGED_BAG(wp);
  return 0;
}

/****************************************************************************
**
*F  IsBoundElmWPObj(<wp>,<pos>) .  . . . . is an entry bound in a WP object
**
**  'IsBoundElmWPObj' returns 1 is there is (currently) a live
**  value at position pos or the WP object wp and  0 otherwise, cleaning up a
**  dead entry if there is one
**
*/

static BOOL IsBoundElmWPObj(Obj wp, UInt ipos)
{
#ifdef HPCGAP
  volatile
#endif
  Obj elm;
  if ( LengthWPObj(wp) < ipos )
    {
      return 0;
    }
  elm = ELM_WPOBJ(wp,ipos);
#ifdef HPCGAP
  MEMBAR_READ();
  if (elm == 0 || ELM_WPOBJ(wp, ipos) == 0)
      return 0;
#else
  if (elm == 0)
      return 0;
#endif
  return 1;
}

/****************************************************************************
**
*F  FuncIsBoundElmWPObj(<self>,<wp>,<pos>) . . IsBound handler for WP objects
**
**  GAP  handler for IsBound  test on WP object.   Remember that bindings can
**  evaporate in any garbage collection.
*/

static Obj FuncIsBoundElmWPObj(Obj self, Obj wp, Obj pos)
{
    RequireWPObj(SELF_NAME, wp);
    UInt ipos = GetPositiveSmallInt(SELF_NAME, pos);

    return IsBoundElmWPObj(wp, ipos) ? True : False;
}


/****************************************************************************
**
*F  FuncUnbindElmWPObj(<self>,<wp>,<pos>) . . . Unbind handler for WP objects
**
**  GAP  handler for Unbind on WP object.
*/


static Obj FuncUnbindElmWPObj(Obj self, Obj wp, Obj pos)
{
    RequireWPObj(SELF_NAME, wp);
    UInt ipos = GetPositiveSmallInt(SELF_NAME, pos);

  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
  }
  return 0;
}


/****************************************************************************
**
*F  ElmDefWPList(<wp>,<ipos>,<def>)
**
**  Provide implementation of 'ElmDefListFuncs'.
*/

static Obj ElmDefWPList(Obj wp, Int ipos, Obj def)
{
    GAP_ASSERT(TNUM_OBJ(wp) == T_WPOBJ);
    GAP_ASSERT(ipos >= 1);

#ifdef HPCGAP
  if ( LengthWPObj(wp) < ipos )
      return def;
#else
  if ( STORED_LEN_WPOBJ(wp) < ipos )
      return def;
#endif

#ifdef USE_BOEHM_GC
  volatile
#endif
  Obj elm = ELM_WPOBJ(wp,ipos);
#ifdef HPCGAP
  MEMBAR_READ();
  if (elm == 0 || ELM_WPOBJ(wp, ipos) == 0)
      return def;
#else
  if (elm == 0)
      return def;
#endif
  return elm;
}


/****************************************************************************
**
*F  FuncElmWPObj(<self>,<wp>,<pos>) . . . . . . . access entry of a WP object
**
**  GAP handler for access to WP object. If the entry is not bound, then fail
**  is  returned. It would not be  correct to return  an error, because there
**  would be no  way  to  safely access  an  element, which  might  evaporate
**  between a  call   to IsBound and the    access. This, of  course,  causes
**  possible  confusion  with a WP  object which  does have  a  value of fail
**  stored in  it. This, however  can be  checked  with a subsequent  call to
**  IsBound, relying on the fact  that fail can never  disappear in a garbage
**  collection.
*/

static Obj FuncElmWPObj(Obj self, Obj wp, Obj pos)
{
    RequireWPObj(SELF_NAME, wp);
    UInt ipos = GetPositiveSmallInt(SELF_NAME, pos);

    return ElmDefWPList(wp, ipos, Fail);
}


/****************************************************************************
**
*F  TypeWPObj(<wp>) . . . . . . . . . . . . . . . . . . . . type of WP object
**
**  This returns the library variable TYPE_WPOBJ. All WP objects have the
**  same type.
*/


static Obj TYPE_WPOBJ;

static Obj TypeWPObj(Obj wp)
{
  return TYPE_WPOBJ;
}


/****************************************************************************
**
*F  FuncIsWPObj(<self>,<wp>) . . . . . . . . handler for GAP function IsWPObj
*/

static Obj IsWPObjFilt;

static Obj FiltIsWPObj(Obj self, Obj wp)
{
  return (TNUM_OBJ(wp) == T_WPOBJ) ? True : False;
}

/****************************************************************************
**
*F  MarkWeakPointerObj(<wp>) . . . . . . . . . . . . . . . . Marking function
*F  SweepWeakPointerObj(<src>,<dst>,<len>) . . . . . . . .  Sweeping function
**
**  These functions are installed for GASMAN to use in garbage collection.
**  The sweeping function must clean up any dead weak pointers encountered so
**  that, after a full GC, the masterpointers occupied by the dead weak
**  pointers can be reclaimed.
*/


#if defined(USE_GASMAN)

static void 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]);
    }
}

static void SweepWeakPointerObj( Bag *src, Bag *dst, UInt len)
{
  Bag elm;
  while (len --)
    {
      elm = *src++;
      *dst ++ = IsWeakDeadBag(elm) ? (Bag) 0 : elm;
    }
}

#endif

#ifdef USE_JULIA_GC

static void 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);
    }
}

#endif


#ifdef USE_THREADSAFE_COPYING
#ifndef WARD_ENABLED
static void TraverseWPObj(TraversalState * traversal, Obj obj)
{
    UInt  len = STORED_LEN_WPOBJ(obj);
    const Obj * ptr = CONST_ADDR_OBJ(obj) + 1;
    while (len) {
        volatile Obj tmp = *ptr;
        MEMBAR_READ();
        if (IS_BAG_REF(tmp) && IS_BAG_REF(*ptr))
            QueueForTraversal(traversal, *ptr);
        ptr++;
        len--;
    }
}

static void CopyWPObj(TraversalState * traversal, Obj copy, Obj original)
{
    UInt  len = STORED_LEN_WPOBJ(original);
    const Obj * ptr = CONST_ADDR_OBJ(original) + 1;
    Obj * copyptr = ADDR_OBJ(copy) + 1;
    while (len--) {
        volatile Obj tmp = *ptr;
        MEMBAR_READ();
        if (IS_BAG_REF(tmp) && IS_BAG_REF(*ptr)) {
            *copyptr = ReplaceByCopy(traversal, tmp);
#ifdef USE_BOEHM_GC
            GC_general_register_disappearing_link((void **)copyptr, tmp);
#endif
        }
        ptr++;
        copyptr++;
    }
}

#endif // WARD_ENABLED

#else

/****************************************************************************
**
*F  CopyObjWPObj(<obj>,<mut>) . . . . . . . . . . . . . . .  copy a WP object
**
**  Note  that an  immutable   copy of  a  weak  pointer  object is a  normal
**  immutable plist. An Immutable WP object is a contradiction.
**
*N  I am far from clear that this is safe from a badly timed GC during copying.
**
*/


static Obj CopyObjWPObj(Obj obj, Int mut)
{
    Obj                 copy;           // copy, result
    Obj                 tmp;            // temporary variable
    Obj                 elm;
    UInt                i;              // loop variable

    // 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 );
        }
    }

    // return the copy
    return copy;
}

#endif // !defined(USE_THREADSAFE_COPYING)


/****************************************************************************
**
*F  MakeImmutableWPObj(<obj>) . . . . . . . . . . . . make immutable in place
**
*/


static void 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);
}

#if !defined(USE_THREADSAFE_COPYING)

/****************************************************************************
**
*F  CleanObjWPObj(<obj>) . . . . . . . . . . . . . . . . . .  clean WP object
*/

static void CleanObjWPObj(Obj obj)
{
    UInt                i;              // loop variable
    Obj                 elm;            // subobject

    // clean the subvalues
    for ( i = 1; i < SIZE_OBJ(obj)/sizeof(Obj); i++ ) {
        elm = ELM_WPOBJ(obj, i);
        if (elm)
            CLEAN_OBJ(elm);
    }

}

#endif //!defined(USE_THREADSAFE_COPYING)


/****************************************************************************
**
*F  SaveWPObj(<wpobj>)
*/

#ifdef GAP_ENABLE_SAVELOAD
static void SaveWPObj(Obj wpobj)
{
    UInt len = STORED_LEN_WPOBJ(wpobj);
    SaveUInt(len);
    for (UInt i = 1; i <= len; i++) {
        SaveSubObj(ELM_WPOBJ(wpobj, i));
    }
}
#endif


/****************************************************************************
**
*F  LoadWPObj(<wpobj>)
*/

#ifdef GAP_ENABLE_SAVELOAD
static void LoadWPObj(Obj wpobj)
{
    const UInt len = LoadUInt();
    STORE_LEN_WPOBJ(wpobj, len);
    for (UInt i = 1; i <= len; i++) {
        SET_ELM_WPOBJ(wpobj, i, LoadSubObj());
    }
}
#endif


/****************************************************************************
**
*F * * * * * * * * * * * * * initialize module * * * * * * * * * * * * * * *
*/



/****************************************************************************
**
*V  BagNames  . . . . . . . . . . . . . . . . . . . . . . . list of bag names
*/

static StructBagNames BagNames[] = {
  { T_WPOBJ, "weak pointer object" },
  { -1,      ""                    }
};


/****************************************************************************
**
*V  GVarFilts . . . . . . . . . . . . . . . . . . . list of filters to export
*/

static StructGVarFilt GVarFilts [] = {

    GVAR_FILT(IsWPObj, "obj", &IsWPObjFilt),
    { 0, 0, 0, 0, 0 }

};


/****************************************************************************
**
*V  GVarFuncs . . . . . . . . . . . . . . . . . . list of functions to export
*/

static StructGVarFunc GVarFuncs [] = {

    GVAR_FUNC_1ARGS(WeakPointerObj, list),
    GVAR_FUNC_1ARGS(LengthWPObj, wp),
    GVAR_FUNC_3ARGS(SetElmWPObj, wp, pos, val),
    GVAR_FUNC_2ARGS(IsBoundElmWPObj, wp, pos),
    GVAR_FUNC_2ARGS(UnbindElmWPObj, wp, pos),
    GVAR_FUNC_2ARGS(ElmWPObj, wp, pos),
    { 0, 0, 0, 0, 0 }

};


/****************************************************************************
**
*F  InitKernel(<module>) . . . . . . . . .  initialise kernel data structures
*/

static Int InitKernel (
    StructInitInfo *    module )
{
    // set the bag type names (for error messages and debugging)
    InitBagNamesFromTable( BagNames );

    // install the marking and sweeping methods
#if defined(USE_BOEHM_GC)
    // force atomic allocation of these pointers
    InitMarkFuncBags ( T_WPOBJ,          MarkNoSubBags   );
#elif defined(USE_GASMAN)
    InitMarkFuncBags ( T_WPOBJ,          MarkWeakPointerObj   );
    InitSweepFuncBags( T_WPOBJ,          SweepWeakPointerObj  );
#elif defined(USE_JULIA_GC)
    InitMarkFuncBags ( T_WPOBJ,          MarkWeakPointerObj   );
#else
#error Unknown garbage collector implementation, no weak pointer object implementation available
#endif

    // typing method
    TypeObjFuncs[ T_WPOBJ ] = TypeWPObj;
    ImportGVarFromLibrary( "TYPE_WPOBJ", &TYPE_WPOBJ );

    // init filters and functions
    InitHdlrFiltsFromTable( GVarFilts );
    InitHdlrFuncsFromTable( GVarFuncs );

    // saving function
#ifdef GAP_ENABLE_SAVELOAD
    SaveObjFuncs[ T_WPOBJ ] = SaveWPObj;
    LoadObjFuncs[ T_WPOBJ ] = LoadWPObj;
#endif

    // List functions
    ElmDefListFuncs[T_WPOBJ] = ElmDefWPList;

#ifdef USE_THREADSAFE_COPYING
    SetTraversalMethod(T_WPOBJ, TRAVERSE_BY_FUNCTION, TraverseWPObj, CopyWPObj);
#else
    // copying functions
    CopyObjFuncs[  T_WPOBJ           ] = CopyObjWPObj;
    CleanObjFuncs[ T_WPOBJ           ] = CleanObjWPObj;
#endif

    MakeImmutableObjFuncs[ T_WPOBJ ] = MakeImmutableWPObj;
    return 0;
}


/****************************************************************************
**
*F  InitLibrary(<module>) . . . . . . . .  initialise library data structures
*/

static Int InitLibrary (
    StructInitInfo *    module )
{
    // init filters and functions
    InitGVarFiltsFromTable( GVarFilts );
    InitGVarFuncsFromTable( GVarFuncs );

    return 0;
}


/****************************************************************************
**
*F  InitInfoWeakPtr() . . . . . . . . . . . . . . . . table of init functions
*/

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,
};

StructInitInfo * InitInfoWeakPtr ( void )
{
    return &module;
}

87%


¤ Dauer der Verarbeitung: 0.33 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

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 ist noch experimentell.