Actual source code: fcallback.c

petsc-3.4.5 2014-06-29
  1: #include <petsc-private/petscimpl.h>  /*I   "petscsys.h"    I*/

  3: typedef struct _FortranCallbackLink *FortranCallbackLink;
  4: struct _FortranCallbackLink {
  5:   char                   *type_name;
  6:   PetscFortranCallbackId max;
  7:   FortranCallbackLink    next;
  8: };

 10: typedef struct {
 11:   PetscInt            basecount;
 12:   PetscInt            maxsubtypecount;
 13:   FortranCallbackLink subtypes;
 14: } FortranCallbackBase;

 16: static FortranCallbackBase *_classbase;
 17: static PetscClassId        _maxclassid = PETSC_SMALLEST_CLASSID;

 21: static PetscErrorCode PetscFortranCallbackFinalize(void)
 22: {
 24:   PetscClassId   i;

 27:   for (i=PETSC_SMALLEST_CLASSID; i<_maxclassid; i++) {
 28:     FortranCallbackBase *base = &_classbase[i-PETSC_SMALLEST_CLASSID];
 29:     FortranCallbackLink next,link = base->subtypes;
 30:     for (; link; link=next) {
 31:       next = link->next;
 32:       PetscFree(link->type_name);
 33:       PetscFree(link);
 34:     }
 35:   }
 36:   PetscFree(_classbase);

 38:   _maxclassid = PETSC_SMALLEST_CLASSID;
 39:   return(0);
 40: }

 44: /*@C
 45:    PetscFortranCallbackRegister - register a type+subtype callback

 47:    Not Collective

 49:    Input Arguments:
 50: +  classid - ID of class on which to register callback
 51: -  subtype - subtype string, or NULL for class ids

 53:    Output Arguments:
 54: .  id - callback id

 56:    Level: developer

 58: .seealso: PetscFortranCallbackGetSizes()
 59: @*/
 60: PetscErrorCode PetscFortranCallbackRegister(PetscClassId classid,const char *subtype,PetscFortranCallbackId *id)
 61: {
 62:   PetscErrorCode      ierr;
 63:   FortranCallbackBase *base;
 64:   FortranCallbackLink link;

 67:   *id = 0;
 68:   if (classid < PETSC_SMALLEST_CLASSID || PETSC_LARGEST_CLASSID <= classid) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"ClassId %D corrupt",classid);
 69:   if (classid >= _maxclassid) {
 70:     PetscClassId        newmax = PETSC_SMALLEST_CLASSID + 2*(PETSC_LARGEST_CLASSID-PETSC_SMALLEST_CLASSID);
 71:     FortranCallbackBase *newbase;
 72:     if (!_classbase) {
 73:       PetscRegisterFinalize(PetscFortranCallbackFinalize);
 74:     }
 75:     PetscMalloc((newmax-PETSC_SMALLEST_CLASSID)*sizeof(_classbase[0]),&newbase);
 76:     PetscMemzero(newbase,(newmax-PETSC_SMALLEST_CLASSID)*sizeof(_classbase[0]));
 77:     PetscMemcpy(newbase,_classbase,(_maxclassid-PETSC_SMALLEST_CLASSID)*sizeof(_classbase[0]));
 78:     PetscFree(_classbase);

 80:     _classbase = newbase;
 81:     _maxclassid = newmax;
 82:   }
 83:   base = &_classbase[classid-PETSC_SMALLEST_CLASSID];
 84:   if (!subtype) *id = PETSC_SMALLEST_FORTRAN_CALLBACK + base->basecount++;
 85:   else {
 86:     for (link=base->subtypes; link; link=link->next) { /* look for either both NULL or matching values (implies both non-NULL) */
 87:       PetscBool match;
 88:       PetscStrcmp(subtype,link->type_name,&match);
 89:       if (match) { /* base type or matching subtype */
 90:         goto found;
 91:       }
 92:     }
 93:     /* Not found. Create node and prepend to class' subtype list */
 94:     PetscMalloc(sizeof(*link),&link);
 95:     PetscStrallocpy(subtype,&link->type_name);

 97:     link->max      = PETSC_SMALLEST_FORTRAN_CALLBACK;
 98:     link->next     = base->subtypes;
 99:     base->subtypes = link;

101: found:
102:     *id = link->max++;

104:     base->maxsubtypecount = PetscMax(base->maxsubtypecount,link->max-PETSC_SMALLEST_FORTRAN_CALLBACK);
105:   }
106:   return(0);
107: }

111: /*@C
112:    PetscFortranCallbackGetSizes - get sizes of class and subtype pointer arrays

114:    Collective

116:    Input Arguments:
117: .  classid - class Id

119:    Output Arguments:
120: +  numbase - number of registered class callbacks
121: -  numsubtype - max number of registered subtype callbacks

123:    Level: developer

125: .seealso: PetscFortranCallbackRegister()
126: @*/
127: PetscErrorCode PetscFortranCallbackGetSizes(PetscClassId classid,PetscInt *numbase,PetscInt *numsubtype)
128: {

131:   if (classid < _maxclassid) {
132:     FortranCallbackBase *base = &_classbase[classid-PETSC_SMALLEST_CLASSID];
133:     *numbase    = base->basecount;
134:     *numsubtype = base->maxsubtypecount;
135:   } else {                      /* nothing registered */
136:     *numbase    = 0;
137:     *numsubtype = 0;
138:   }
139:   return(0);
140: }