Actual source code: olist.c

petsc-3.14.6 2021-03-30
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 = NULL;
 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 = NULL;
 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 = NULL;
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: .   obj - 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 = NULL;
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: -   obj - the PETSc object

211:     Output Parameters:
212: +  name - name string
213: -  skipdereference - if the object is in 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 = NULL;
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 given 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: }