Actual source code: olist.c

petsc-3.4.5 2014-06-29
  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: }