Initializing help system before first use

Mosel memory management

Topics covered in this section:

In place of implementing dedicated memory management for a module developers can use the NI subroutines memalloc and memfree that rely on Mosel memory management and are particularly suited for frequent allocation/deallocation of small chunks of memory. Besides simplifying considerably the code presented in the previous section these routines will also make sure that all memory allocated by a module gets freed when it is unloaded.

With this implementation option we no longer need to create a module context given that Mosel will keep track of all memory allocations.

Service functions reset and memuse

The reset service function is reduced to creating a dummy context for use by the equally considerably reduced memory use (memuse) service function that no longer needs to calculate any total memory use by the module:

static void *cx_reset(XPRMcontext ctx,void *libctx,int version)
{
 if(libctx==NULL)               /* libctx==NULL => initialisation */
  return (void*)1l;
 else
  return NULL;
}

static size_t cx_memuse(XPRMcontext ctx,void *libctx,void *ref,int code)
{
 switch(code)
 {
  case 0:
    return 0;
  case 1:
    return sizeof(s_complex);
  default:
    return -1;
 }
}

Type creation and deletion functions

The type creation function relies on Mosel memory management (memalloc) for the allocation of new complex numbers. If the complex number passed into the creation function already exists we simply augment its reference counter, unless the object is shared (note that just like the previous version the implementation of the shared data property shown in this example is not entirely complete: it should guarantee that concurrent access to a given shared object does not corrupt the data structure, e.g. by using critical sections).

static void *cx_create(XPRMcontext ctx,void *libctx,void *todup,int typnum)
{
 s_complex *complex;

 if((todup!=NULL)&&(XPRM_CREATE(typnum)==XPRM_CREATE_NEW))
 {
  /* Do not update the reference count if the object is shared */
  if((((s_complex *)todup)->refcnt&CX_SHARED)==0)
   ((s_complex *)todup)->refcnt++;
  return todup;
 }
 else
 {
  complex=mm->memalloc(ctx,sizeof(s_complex),0);
  if(XPRM_CREATE(typnum)==XPRM_CREATE_CST)
  {
   complex->re=((s_complex *)todup)->re;
   complex->im=((s_complex *)todup)->im;
   complex->refcnt=1|CX_CONST;
  }
  else
  {
   complex->re=complex->im=0;
   complex->refcnt=1;
   /* Tag a shared complex number to disable reference counting */
   if(XPRM_CREATE(typnum)==XPRM_CREATE_SHR)
    complex->refcnt|=CX_SHARED;
  }
  return complex;
 }
}

The deletion function handles the deallocation of memory via the corresponding Mosel routine memfree and ensures suitable decrease of the reference counter:

static void cx_delete(XPRMcontext ctx,void *libctx,void *todel,int typnum)
{
 u_freelist *freelist;

 if((todel!=NULL)&&((((s_complex *)todel)->refcnt&CX_SHARED)==0)&&
    (((--((s_complex *)todel)->refcnt)&~CX_CONST)<1))
 {
  mm->memfree(ctx,todel,sizeof(s_complex));
 }
}

© 2001-2022 Fair Isaac Corporation. All rights reserved. This documentation is the property of Fair Isaac Corporation (“FICO”). Receipt or possession of this documentation does not convey rights to disclose, reproduce, make derivative works, use, or allow others to use it except solely for internal evaluation purposes to determine whether to purchase a license to the software described in this documentation, or as otherwise set forth in a written software license agreement between you and FICO (or a FICO affiliate). Use of this documentation and the software described in it must conform strictly to the foregoing permitted uses, and no other use is permitted.