Actual source code: olist.c
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: }
165: /*@C
166: PetscObjectListFind - givn a name, find the matching object
168: Input Parameters:
169: + fl - pointer to list
170: - name - name string
172: Output Parameters:
173: . obj - the PETSc object
175: Level: developer
177: Notes:
178: The name must have been registered with the PetscObjectListAdd() before calling this routine.
180: The reference count of the object is not increased
182: .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate()
184: @*/
185: PetscErrorCode PetscObjectListFind(PetscObjectList fl,const char name[],PetscObject *obj)
186: {
188: PetscBool match;
191: *obj = NULL;
192: while (fl) {
193: PetscStrcmp(name,fl->name,&match);
194: if (match) {
195: *obj = fl->obj;
196: break;
197: }
198: fl = fl->next;
199: }
200: return(0);
201: }
203: /*@C
204: PetscObjectListReverseFind - given a object, find the matching name if it exists
206: Input Parameters:
207: + fl - pointer to list
208: - obj - the PETSc object
210: Output Parameters:
211: + name - name string
212: - skipdereference - if the object is in list but does not have the increased reference count for a circular dependency
214: Level: developer
216: Notes:
217: The name must have been registered with the PetscObjectListAdd() before calling this routine.
219: The reference count of the object is not increased
221: .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListFind(), PetscObjectListDuplicate()
223: @*/
224: PetscErrorCode PetscObjectListReverseFind(PetscObjectList fl,PetscObject obj,char **name,PetscBool *skipdereference)
225: {
227: *name = NULL;
228: while (fl) {
229: if (fl->obj == obj) {
230: *name = fl->name;
231: if (skipdereference) *skipdereference = fl->skipdereference;
232: break;
233: }
234: fl = fl->next;
235: }
236: return(0);
237: }
239: /*@C
240: PetscObjectListDuplicate - Creates a new list from a given object list.
242: Input Parameters:
243: . fl - pointer to list
245: Output Parameters:
246: . nl - the new list (should point to 0 to start, otherwise appends)
248: Level: developer
250: .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListReverseFind(), PetscObjectListFind(), PetscObjectListDuplicate()
252: @*/
253: PetscErrorCode PetscObjectListDuplicate(PetscObjectList fl,PetscObjectList *nl)
254: {
258: while (fl) {
259: PetscObjectListAdd(nl,fl->name,fl->obj);
260: fl = fl->next;
261: }
262: return(0);
263: }