Actual source code: olist.c
petsc-3.6.4 2016-04-12
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: /* Remove it first to prevent circular derefs */
89: if (prev) prev->next = nlist->next;
90: else if (nlist->next) *fl = nlist->next;
91: else *fl = 0;
92: if (!nlist->skipdereference) {
93: PetscObjectDereference(nlist->obj);
94: }
95: PetscFree(nlist);
96: return(0);
97: }
98: prev = nlist;
99: nlist = nlist->next;
100: }
101: return(0); /* did not find it to remove */
102: }
103: /* look for it already in list */
104: nlist = *fl;
105: while (nlist) {
106: PetscStrcmp(name,nlist->name,&match);
107: if (match) { /* found it in the list */
108: PetscObjectReference(obj);
109: if (!nlist->skipdereference) {
110: PetscObjectDereference(nlist->obj);
111: }
112: nlist->skipdereference = PETSC_FALSE;
113: nlist->obj = obj;
114: return(0);
115: }
116: nlist = nlist->next;
117: }
119: /* add it to list, because it was not already there */
120: PetscNew(&olist);
121: olist->next = 0;
122: olist->obj = obj;
124: PetscObjectReference(obj);
125: PetscStrcpy(olist->name,name);
127: if (!*fl) *fl = olist;
128: else { /* go to end of list */
129: nlist = *fl;
130: while (nlist->next) {
131: nlist = nlist->next;
132: }
133: nlist->next = olist;
134: }
135: return(0);
136: }
140: /*@C
141: PetscObjectListDestroy - Destroy a list of objects
143: Input Parameter:
144: . ifl - pointer to list
146: Level: developer
148: .seealso: PetscObjectListAdd(), PetscObjectListFind(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate()
150: @*/
151: PetscErrorCode PetscObjectListDestroy(PetscObjectList *ifl)
152: {
153: PetscObjectList tmp,fl = *ifl;
154: PetscErrorCode ierr;
157: while (fl) {
158: tmp = fl->next;
159: if (!fl->skipdereference) {
160: PetscObjectDereference(fl->obj);
161: }
162: PetscFree(fl);
163: fl = tmp;
164: }
165: *ifl = NULL;
166: return(0);
167: }
172: /*@C
173: PetscObjectListFind - givn a name, find the matching object
175: Input Parameters:
176: + fl - pointer to list
177: - name - name string
179: Output Parameters:
180: . ob - the PETSc object
182: Level: developer
184: Notes:
185: The name must have been registered with the PetscObjectListAdd() before calling this routine.
187: The reference count of the object is not increased
189: .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate()
191: @*/
192: PetscErrorCode PetscObjectListFind(PetscObjectList fl,const char name[],PetscObject *obj)
193: {
195: PetscBool match;
198: *obj = 0;
199: while (fl) {
200: PetscStrcmp(name,fl->name,&match);
201: if (match) {
202: *obj = fl->obj;
203: break;
204: }
205: fl = fl->next;
206: }
207: return(0);
208: }
212: /*@C
213: PetscObjectListReverseFind - given a object, find the matching name if it exists
215: Input Parameters:
216: + fl - pointer to list
217: - ob - the PETSc object
219: Output Parameters:
220: + name - name string
221: - skipdereference - if the object is list but does not have the increased reference count for a circular dependency
223: Level: developer
225: Notes:
226: The name must have been registered with the PetscObjectListAdd() before calling this routine.
228: The reference count of the object is not increased
230: .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListFind(), PetscObjectListDuplicate()
232: @*/
233: PetscErrorCode PetscObjectListReverseFind(PetscObjectList fl,PetscObject obj,char **name,PetscBool *skipdereference)
234: {
236: *name = 0;
237: while (fl) {
238: if (fl->obj == obj) {
239: *name = fl->name;
240: if (skipdereference) *skipdereference = fl->skipdereference;
241: break;
242: }
243: fl = fl->next;
244: }
245: return(0);
246: }
250: /*@C
251: PetscObjectListDuplicate - Creates a new list from a give object list.
253: Input Parameters:
254: . fl - pointer to list
256: Output Parameters:
257: . nl - the new list (should point to 0 to start, otherwise appends)
259: Level: developer
261: .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListReverseFind(), PetscObjectListFind(), PetscObjectListDuplicate()
263: @*/
264: PetscErrorCode PetscObjectListDuplicate(PetscObjectList fl,PetscObjectList *nl)
265: {
269: while (fl) {
270: PetscObjectListAdd(nl,fl->name,fl->obj);
271: fl = fl->next;
272: }
273: return(0);
274: }