Actual source code: olist.c

petsc-3.5.4 2015-05-23
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: }