Actual source code: olist.c
petsc-3.7.1 2016-05-15
Report Typos and Errors

      2: /*
      3:          Provides a general mechanism to maintain a linked list of PETSc objects.
      4:      This is used to allow PETSc objects to carry a list of "composed" objects
      5: */
      6: #include <petscsys.h>

      8: struct _n_PetscObjectList {
      9:   char            name[256];
     10:   PetscBool       skipdereference;      /* when the PetscObjectList is destroyed do not call PetscObjectDereference() on this object */
     11:   PetscObject     obj;
     12:   PetscObjectList next;
     13: };

     17: /*@C
     18:      PetscObjectListRemoveReference - Calls PetscObjectDereference() on an object in the list immediately but keeps a pointer to the object in the list.

     20:     Input Parameters:
     21: +     fl - the object list
     22: -     name - the name to use for the object

     24:     Level: developer

     26:        Notes: Use PetscObjectListAdd(PetscObjectList,const char name[],NULL) to truly remove the object from the list

     28:               Use this routine ONLY if you know that the object referenced will remain in existence until the pointing object is destroyed

     30:       Developer Note: this is to handle some cases that otherwise would result in having circular references so reference counts never got to zero

     32: .seealso: PetscObjectListDestroy(), PetscObjectListFind(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate(), PetscObjectListAdd()

     34: @*/
     35: PetscErrorCode  PetscObjectListRemoveReference(PetscObjectList *fl,const char name[])
     36: {
     37:   PetscObjectList nlist;
     38:   PetscErrorCode  ierr;
     39:   PetscBool       match;

     42:   nlist = *fl;
     43:   while (nlist) {
     44:     PetscStrcmp(name,nlist->name,&match);
     45:     if (match) { /* found it in the list */
     46:       if (!nlist->skipdereference) {
     47:         PetscObjectDereference(nlist->obj);
     48:       }
     49:       nlist->skipdereference = PETSC_TRUE;
     50:       return(0);
     51:     }
     52:     nlist = nlist->next;
     53:   }
     54:   return(0);
     55: }

     59: /*@C
     60:      PetscObjectListAdd - Adds a new object to an PetscObjectList

     62:     Input Parameters:
     63: +     fl - the object list
     64: .     name - the name to use for the object
     65: -     obj - the object to attach

     67:     Level: developer

     69:        Notes: Replaces item if it is already in list. Removes item if you pass in a NULL object.

     71:         Use PetscObjectListFind() or PetscObjectListReverseFind() to get the object back

     73: .seealso: PetscObjectListDestroy(), PetscObjectListFind(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate()

     75: @*/
     76: PetscErrorCode  PetscObjectListAdd(PetscObjectList *fl,const char name[],PetscObject obj)
     77: {
     78:   PetscObjectList olist,nlist,prev;
     79:   PetscErrorCode  ierr;
     80:   PetscBool       match;

     83:   if (!obj) { /* this means remove from list if it is there */
     84:     nlist = *fl; prev = 0;
     85:     while (nlist) {
     86:       PetscStrcmp(name,nlist->name,&match);
     87:       if (match) {  /* found it already in the list */
     88:         /* Remove it first to prevent circular derefs */
     89:         if (prev) prev->next = nlist->next;
     90:         else if (nlist->next) *fl = nlist->next;
     91:         else *fl = 0;
     92:         if (!nlist->skipdereference) {
     93:           PetscObjectDereference(nlist->obj);
     94:         }
     95:         PetscFree(nlist);
     96:         return(0);
     97:       }
     98:       prev  = nlist;
     99:       nlist = nlist->next;
    100:     }
    101:     return(0); /* did not find it to remove */
    102:   }
    103:   /* look for it already in list */
    104:   nlist = *fl;
    105:   while (nlist) {
    106:     PetscStrcmp(name,nlist->name,&match);
    107:     if (match) {  /* found it in the list */
    108:       PetscObjectReference(obj);
    109:       if (!nlist->skipdereference) {
    110:         PetscObjectDereference(nlist->obj);
    111:       }
    112:       nlist->skipdereference = PETSC_FALSE;
    113:       nlist->obj             = obj;
    114:       return(0);
    115:     }
    116:     nlist = nlist->next;
    117:   }

    119:   /* add it to list, because it was not already there */
    120:   PetscNew(&olist);
    121:   olist->next = 0;
    122:   olist->obj  = obj;

    124:   PetscObjectReference(obj);
    125:   PetscStrcpy(olist->name,name);

    127:   if (!*fl) *fl = olist;
    128:   else { /* go to end of list */
    129:     nlist = *fl;
    130:     while (nlist->next) {
    131:       nlist = nlist->next;
    132:     }
    133:     nlist->next = olist;
    134:   }
    135:   return(0);
    136: }

    140: /*@C
    141:     PetscObjectListDestroy - Destroy a list of objects

    143:     Input Parameter:
    144: .   ifl   - pointer to list

    146:     Level: developer

    148: .seealso: PetscObjectListAdd(), PetscObjectListFind(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate()

    150: @*/
    151: PetscErrorCode  PetscObjectListDestroy(PetscObjectList *ifl)
    152: {
    153:   PetscObjectList tmp,fl = *ifl;
    154:   PetscErrorCode  ierr;

    157:   while (fl) {
    158:     tmp = fl->next;
    159:     if (!fl->skipdereference) {
    160:       PetscObjectDereference(fl->obj);
    161:     }
    162:     PetscFree(fl);
    163:     fl   = tmp;
    164:   }
    165:   *ifl = NULL;
    166:   return(0);
    167: }

    172: /*@C
    173:     PetscObjectListFind - givn a name, find the matching object

    175:     Input Parameters:
    176: +   fl   - pointer to list
    177: -   name - name string

    179:     Output Parameters:
    180: .   ob - the PETSc object

    182:     Level: developer

    184:     Notes:
    185:     The name must have been registered with the PetscObjectListAdd() before calling this routine.

    187:     The reference count of the object is not increased

    189: .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate()

    191: @*/
    192: PetscErrorCode  PetscObjectListFind(PetscObjectList fl,const char name[],PetscObject *obj)
    193: {
    195:   PetscBool      match;

    198:   *obj = 0;
    199:   while (fl) {
    200:     PetscStrcmp(name,fl->name,&match);
    201:     if (match) {
    202:       *obj = fl->obj;
    203:       break;
    204:     }
    205:     fl = fl->next;
    206:   }
    207:   return(0);
    208: }

    212: /*@C
    213:     PetscObjectListReverseFind - given a object, find the matching name if it exists

    215:     Input Parameters:
    216: +   fl   - pointer to list
    217: -   ob - the PETSc object

    219:     Output Parameters:
    220: +  name - name string
    221: -  skipdereference - if the object is list but does not have the increased reference count for a circular dependency

    223:     Level: developer

    225:     Notes:
    226:     The name must have been registered with the PetscObjectListAdd() before calling this routine.

    228:     The reference count of the object is not increased

    230: .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListFind(), PetscObjectListDuplicate()

    232: @*/
    233: PetscErrorCode  PetscObjectListReverseFind(PetscObjectList fl,PetscObject obj,char **name,PetscBool *skipdereference)
    234: {
    236:   *name = 0;
    237:   while (fl) {
    238:     if (fl->obj == obj) {
    239:       *name = fl->name;
    240:       if (skipdereference) *skipdereference = fl->skipdereference;
    241:       break;
    242:     }
    243:     fl = fl->next;
    244:   }
    245:   return(0);
    246: }

    250: /*@C
    251:     PetscObjectListDuplicate - Creates a new list from a give object list.

    253:     Input Parameters:
    254: .   fl   - pointer to list

    256:     Output Parameters:
    257: .   nl - the new list (should point to 0 to start, otherwise appends)

    259:     Level: developer

    261: .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListReverseFind(), PetscObjectListFind(), PetscObjectListDuplicate()

    263: @*/
    264: PetscErrorCode  PetscObjectListDuplicate(PetscObjectList fl,PetscObjectList *nl)
    265: {

    269:   while (fl) {
    270:     PetscObjectListAdd(nl,fl->name,fl->obj);
    271:     fl   = fl->next;
    272:   }
    273:   return(0);
    274: }