Actual source code: olist.c
petsc-3.10.5 2019-03-28
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: };

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

     18:     Input Parameters:
     19: +     fl - the object list
     20: -     name - the name to use for the object

     22:     Level: developer

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

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

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

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

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

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

     56: /*@C
     57:      PetscObjectListAdd - Adds a new object to an PetscObjectList

     59:     Input Parameters:
     60: +     fl - the object list
     61: .     name - the name to use for the object
     62: -     obj - the object to attach

     64:     Level: developer

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

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

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

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

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

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

    122:   PetscObjectReference(obj);
    123:   PetscStrcpy(olist->name,name);

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

    136: /*@C
    137:     PetscObjectListDestroy - Destroy a list of objects

    139:     Input Parameter:
    140: .   ifl   - pointer to list

    142:     Level: developer

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

    146: @*/
    147: PetscErrorCode  PetscObjectListDestroy(PetscObjectList *ifl)
    148: {
    149:   PetscObjectList tmp,fl = *ifl;
    150:   PetscErrorCode  ierr;

    153:   while (fl) {
    154:     tmp = fl->next;
    155:     if (!fl->skipdereference) {
    156:       PetscObjectDereference(fl->obj);
    157:     }
    158:     PetscFree(fl);
    159:     fl   = tmp;
    160:   }
    161:   *ifl = NULL;
    162:   return(0);
    163: }

    166: /*@C
    167:     PetscObjectListFind - givn a name, find the matching object

    169:     Input Parameters:
    170: +   fl   - pointer to list
    171: -   name - name string

    173:     Output Parameters:
    174: .   ob - the PETSc object

    176:     Level: developer

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

    181:     The reference count of the object is not increased

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

    185: @*/
    186: PetscErrorCode  PetscObjectListFind(PetscObjectList fl,const char name[],PetscObject *obj)
    187: {
    189:   PetscBool      match;

    192:   *obj = 0;
    193:   while (fl) {
    194:     PetscStrcmp(name,fl->name,&match);
    195:     if (match) {
    196:       *obj = fl->obj;
    197:       break;
    198:     }
    199:     fl = fl->next;
    200:   }
    201:   return(0);
    202: }

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

    207:     Input Parameters:
    208: +   fl   - pointer to list
    209: -   ob - the PETSc object

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

    215:     Level: developer

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

    220:     The reference count of the object is not increased

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

    224: @*/
    225: PetscErrorCode  PetscObjectListReverseFind(PetscObjectList fl,PetscObject obj,char **name,PetscBool *skipdereference)
    226: {
    228:   *name = 0;
    229:   while (fl) {
    230:     if (fl->obj == obj) {
    231:       *name = fl->name;
    232:       if (skipdereference) *skipdereference = fl->skipdereference;
    233:       break;
    234:     }
    235:     fl = fl->next;
    236:   }
    237:   return(0);
    238: }

    240: /*@C
    241:     PetscObjectListDuplicate - Creates a new list from a give object list.

    243:     Input Parameters:
    244: .   fl   - pointer to list

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

    249:     Level: developer

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

    253: @*/
    254: PetscErrorCode  PetscObjectListDuplicate(PetscObjectList fl,PetscObjectList *nl)
    255: {

    259:   while (fl) {
    260:     PetscObjectListAdd(nl,fl->name,fl->obj);
    261:     fl   = fl->next;
    262:   }
    263:   return(0);
    264: }