Date: 2013-07-02T14:38:51+00:00

Actual source code: olist.c
petsc-3.4.2 2013-07-02

      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:         if (!nlist->skipdereference) {
     89:           PetscObjectDereference(nlist->obj);
     90:         }
     91:         if (prev) prev->next = nlist->next;
     92:         else if (nlist->next) *fl = nlist->next;
     93:         else *fl = 0;
     94:         PetscFree(nlist);
     95:         return(0);
     96:       }
     97:       prev  = nlist;
     98:       nlist = nlist->next;
     99:     }
    100:     return(0); /* did not find it to remove */
    101:   }
    102:   /* look for it already in list */
    103:   nlist = *fl;
    104:   while (nlist) {
    105:     PetscStrcmp(name,nlist->name,&match);
    106:     if (match) {  /* found it in the list */
    107:       PetscObjectReference(obj);
    108:       if (!nlist->skipdereference) {
    109:         PetscObjectDereference(nlist->obj);
    110:       }
    111:       nlist->skipdereference = PETSC_FALSE;
    112:       nlist->obj             = obj;
    113:       return(0);
    114:     }
    115:     nlist = nlist->next;
    116:   }

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

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

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

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

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

    145:     Level: developer

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

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

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

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

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

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

    181:     Level: developer

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

    186:     The reference count of the object is not increased

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

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

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

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

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

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

    222:     Level: developer

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

    227:     The reference count of the object is not increased

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

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

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

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

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

    258:     Level: developer

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

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

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