Actual source code: olist.c

petsc-3.3-p7 2013-05-11
  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_PetscOList {
  9:     char        name[256];
 10:     PetscBool   skipdereference;   /* when the OList is destroyed do not call PetscObjectDereference() on this object */
 11:     PetscObject obj;
 12:     PetscOList  next;
 13: };

 17: /*@C
 18:      PetscOListRemoveReference - 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 PetscOListAdd(PetscOList,const char name[],PETSC_NULL) to truly remove the object from the list
 27:  
 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: PetscOListDestroy(), PetscOListFind(), PetscOListDuplicate(), PetscOListReverseFind(), PetscOListDuplicate(), PetscOListAdd()

 34: @*/
 35: PetscErrorCode  PetscOListRemoveReference(PetscOList *fl,const char name[])
 36: {
 37:   PetscOList     nlist;
 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:      PetscOListAdd - Adds a new object to an PetscOList

 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 PETSC_NULL object.    
 70:  
 71:         Use PetscOListFind() or PetscOListReverseFind() to get the object back

 73: .seealso: PetscOListDestroy(), PetscOListFind(), PetscOListDuplicate(), PetscOListReverseFind(), PetscOListDuplicate()

 75: @*/
 76: PetscErrorCode  PetscOListAdd(PetscOList *fl,const char name[],PetscObject obj)
 77: {
 78:   PetscOList     olist,nlist,prev;
 80:   PetscBool      match;


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

122:   /* add it to list, because it was not already there */
123:   PetscNew(struct _n_PetscOList,&olist);
124:   olist->next = 0;
125:   olist->obj  = obj;
126:   PetscObjectReference(obj);
127:   PetscStrcpy(olist->name,name);

129:   if (!*fl) {
130:     *fl = olist;
131:   } else { /* go to end of list */
132:     nlist = *fl;
133:     while (nlist->next) {
134:       nlist = nlist->next;
135:     }
136:     nlist->next = olist;
137:   }
138:   return(0);
139: }

143: /*@C
144:     PetscOListDestroy - Destroy a list of objects

146:     Input Parameter:
147: .   ifl   - pointer to list

149:     Level: developer

151: .seealso: PetscOListAdd(), PetscOListFind(), PetscOListDuplicate(), PetscOListReverseFind(), PetscOListDuplicate()

153: @*/
154: PetscErrorCode  PetscOListDestroy(PetscOList *ifl)
155: {
156:   PetscOList     tmp,fl = *ifl;

160:   while (fl) {
161:     tmp   = fl->next;
162:     if (!fl->skipdereference) {
163:       PetscObjectDereference(fl->obj);
164:     }
165:     PetscFree(fl);
166:     fl    = tmp;
167:   }
168:   *ifl = PETSC_NULL;
169:   return(0);
170: }


175: /*@C
176:     PetscOListFind - givn a name, find the matching object

178:     Input Parameters:
179: +   fl   - pointer to list
180: -   name - name string

182:     Output Parameters:
183: .   ob - the PETSc object

185:     Level: developer

187:     Notes:
188:     The name must have been registered with the PetscOListAdd() before calling this routine.

190:     The reference count of the object is not increased

192: .seealso: PetscOListDestroy(), PetscOListAdd(), PetscOListDuplicate(), PetscOListReverseFind(), PetscOListDuplicate()

194: @*/
195: PetscErrorCode  PetscOListFind(PetscOList fl,const char name[],PetscObject *obj)
196: {
198:   PetscBool      match;

201:   *obj = 0;
202:   while (fl) {
203:     PetscStrcmp(name,fl->name,&match);
204:     if (match) {
205:       *obj = fl->obj;
206:       break;
207:     }
208:     fl = fl->next;
209:   }
210:   return(0);
211: }

215: /*@C
216:     PetscOListReverseFind - given a object, find the matching name if it exists

218:     Input Parameters:
219: +   fl   - pointer to list
220: -   ob - the PETSc object

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

226:     Level: developer

228:     Notes:
229:     The name must have been registered with the PetscOListAdd() before calling this routine.

231:     The reference count of the object is not increased

233: .seealso: PetscOListDestroy(), PetscOListAdd(), PetscOListDuplicate(), PetscOListFind(), PetscOListDuplicate()

235: @*/
236: PetscErrorCode  PetscOListReverseFind(PetscOList fl,PetscObject obj,char **name,PetscBool *skipdereference)
237: {
239:   *name = 0;
240:   while (fl) {
241:     if (fl->obj == obj) {
242:       *name = fl->name;
243:       if (skipdereference) *skipdereference = fl->skipdereference;
244:       break;
245:     }
246:     fl = fl->next;
247:   }
248:   return(0);
249: }

253: /*@C
254:     PetscOListDuplicate - Creates a new list from a give object list.

256:     Input Parameters:
257: .   fl   - pointer to list

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

262:     Level: developer

264: .seealso: PetscOListDestroy(), PetscOListAdd(), PetscOListReverseFind(), PetscOListFind(), PetscOListDuplicate()

266: @*/
267: PetscErrorCode  PetscOListDuplicate(PetscOList fl,PetscOList *nl)
268: {

272:   while (fl) {
273:     PetscOListAdd(nl,fl->name,fl->obj);
274:     fl = fl->next;
275:   }
276:   return(0);
277: }