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: }