Actual source code: olist.c

petsc-3.9.0 2018-04-07
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: Use PetscObjectListAdd(PetscObjectList,const char name[],NULL) to truly remove the object from the list

 26:               Use this routine ONLY if you know that the object referenced will remain in existence until the pointing object is destroyed

 28:       Developer Note: this is to handle some cases that otherwise would result in having circular references so reference counts never got to zero

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

 32: @*/
 33: PetscErrorCode  PetscObjectListRemoveReference(PetscObjectList *fl,const char name[])
 34: {
 35:   PetscObjectList nlist;
 36:   PetscErrorCode  ierr;
 37:   PetscBool       match;

 40:   nlist = *fl;
 41:   while (nlist) {
 42:     PetscStrcmp(name,nlist->name,&match);
 43:     if (match) { /* found it in the list */
 44:       if (!nlist->skipdereference) {
 45:         PetscObjectDereference(nlist->obj);
 46:       }
 47:       nlist->skipdereference = PETSC_TRUE;
 48:       return(0);
 49:     }
 50:     nlist = nlist->next;
 51:   }
 52:   return(0);
 53: }

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

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

 63:     Level: developer

 65:        Notes: 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:   PetscErrorCode  ierr;
 76:   PetscBool       match;

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

115:   /* add it to list, because it was not already there */
116:   PetscNew(&olist);
117:   olist->next = 0;
118:   olist->obj  = obj;

120:   PetscObjectReference(obj);
121:   PetscStrcpy(olist->name,name);

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

134: /*@C
135:     PetscObjectListDestroy - Destroy a list of objects

137:     Input Parameter:
138: .   ifl   - pointer to list

140:     Level: developer

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

144: @*/
145: PetscErrorCode  PetscObjectListDestroy(PetscObjectList *ifl)
146: {
147:   PetscObjectList tmp,fl = *ifl;
148:   PetscErrorCode  ierr;

151:   while (fl) {
152:     tmp = fl->next;
153:     if (!fl->skipdereference) {
154:       PetscObjectDereference(fl->obj);
155:     }
156:     PetscFree(fl);
157:     fl   = tmp;
158:   }
159:   *ifl = NULL;
160:   return(0);
161: }


164: /*@C
165:     PetscObjectListFind - givn a name, find the matching object

167:     Input Parameters:
168: +   fl   - pointer to list
169: -   name - name string

171:     Output Parameters:
172: .   ob - the PETSc object

174:     Level: developer

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

179:     The reference count of the object is not increased

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

183: @*/
184: PetscErrorCode  PetscObjectListFind(PetscObjectList fl,const char name[],PetscObject *obj)
185: {
187:   PetscBool      match;

190:   *obj = 0;
191:   while (fl) {
192:     PetscStrcmp(name,fl->name,&match);
193:     if (match) {
194:       *obj = fl->obj;
195:       break;
196:     }
197:     fl = fl->next;
198:   }
199:   return(0);
200: }

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

205:     Input Parameters:
206: +   fl   - pointer to list
207: -   ob - the PETSc object

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

213:     Level: developer

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

218:     The reference count of the object is not increased

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

222: @*/
223: PetscErrorCode  PetscObjectListReverseFind(PetscObjectList fl,PetscObject obj,char **name,PetscBool *skipdereference)
224: {
226:   *name = 0;
227:   while (fl) {
228:     if (fl->obj == obj) {
229:       *name = fl->name;
230:       if (skipdereference) *skipdereference = fl->skipdereference;
231:       break;
232:     }
233:     fl = fl->next;
234:   }
235:   return(0);
236: }

238: /*@C
239:     PetscObjectListDuplicate - Creates a new list from a give object list.

241:     Input Parameters:
242: .   fl   - pointer to list

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

247:     Level: developer

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

251: @*/
252: PetscErrorCode  PetscObjectListDuplicate(PetscObjectList fl,PetscObjectList *nl)
253: {

257:   while (fl) {
258:     PetscObjectListAdd(nl,fl->name,fl->obj);
259:     fl   = fl->next;
260:   }
261:   return(0);
262: }