Actual source code: olist.c


  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 <petsc/private/petscimpl.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:   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) PetscObjectDereference(nlist->obj);
 46:       nlist->skipdereference = PETSC_TRUE;
 47:       return 0;
 48:     }
 49:     nlist = nlist->next;
 50:   }
 51:   return 0;
 52: }

 54: /*@C
 55:      PetscObjectListAdd - Adds a new object to an PetscObjectList

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

 62:     Level: developer

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

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

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

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

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

110:   /* add it to list, because it was not already there */
111:   PetscNew(&olist);
112:   olist->next = NULL;
113:   olist->obj  = obj;

115:   PetscObjectReference(obj);
116:   PetscStrcpy(olist->name,name);

118:   if (!*fl) *fl = olist;
119:   else { /* go to end of list */
120:     nlist = *fl;
121:     while (nlist->next) nlist = nlist->next;
122:     nlist->next = olist;
123:   }
124:   return 0;
125: }

127: /*@C
128:     PetscObjectListDestroy - Destroy a list of objects

130:     Input Parameter:
131: .   ifl   - pointer to list

133:     Level: developer

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

137: @*/
138: PetscErrorCode  PetscObjectListDestroy(PetscObjectList *ifl)
139: {
140:   PetscObjectList tmp,fl;

143:   fl = *ifl;
144:   while (fl) {
145:     tmp = fl->next;
146:     if (!fl->skipdereference) PetscObjectDereference(fl->obj);
147:     PetscFree(fl);
148:     fl   = tmp;
149:   }
150:   *ifl = NULL;
151:   return 0;
152: }

154: /*@C
155:     PetscObjectListFind - givn a name, find the matching object

157:     Input Parameters:
158: +   fl   - pointer to list
159: -   name - name string

161:     Output Parameters:
162: .   obj - the PETSc object

164:     Level: developer

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

169:     The reference count of the object is not increased

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

173: @*/
174: PetscErrorCode  PetscObjectListFind(PetscObjectList fl,const char name[],PetscObject *obj)
175: {
177:   *obj = NULL;
178:   while (fl) {
179:     PetscBool match;
180:     PetscStrcmp(name,fl->name,&match);
181:     if (match) {
182:       *obj = fl->obj;
183:       break;
184:     }
185:     fl = fl->next;
186:   }
187:   return 0;
188: }

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

193:     Input Parameters:
194: +   fl   - pointer to list
195: -   obj - the PETSc object

197:     Output Parameters:
198: +  name - name string
199: -  skipdereference - if the object is in list but does not have the increased reference count for a circular dependency

201:     Level: developer

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

206:     The reference count of the object is not increased

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

210: @*/
211: PetscErrorCode  PetscObjectListReverseFind(PetscObjectList fl,PetscObject obj,char **name,PetscBool *skipdereference)
212: {
215:   *name = NULL;
216:   while (fl) {
217:     if (fl->obj == obj) {
218:       *name = fl->name;
219:       if (skipdereference) *skipdereference = fl->skipdereference;
220:       break;
221:     }
222:     fl = fl->next;
223:   }
224:   return 0;
225: }

227: /*@C
228:     PetscObjectListDuplicate - Creates a new list from a given object list.

230:     Input Parameters:
231: .   fl   - pointer to list

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

236:     Level: developer

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

240: @*/
241: PetscErrorCode  PetscObjectListDuplicate(PetscObjectList fl,PetscObjectList *nl)
242: {
244:   while (fl) {
245:     PetscObjectListAdd(nl,fl->name,fl->obj);
246:     fl = fl->next;
247:   }
248:   return 0;
249: }