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 <petsc/private/petscimpl.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: 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) PetscObjectDereference(nlist->obj);
46: nlist->skipdereference = PETSC_TRUE;
47: return 0;
48: }
49: nlist = nlist->next;
50: }
51: return 0;
52: }
54: /*@C
55: PetscObjectListAdd - Adds a new object to an PetscObjectList
57: Input Parameters:
58: + fl - the object list
59: . name - the name to use for the object
60: - obj - the object to attach
62: Level: developer
64: Notes:
65: 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: PetscBool match;
78: if (!obj) { /* this means remove from list if it is there */
79: nlist = *fl; prev = NULL;
80: while (nlist) {
81: PetscStrcmp(name,nlist->name,&match);
82: if (match) { /* found it already in the list */
83: /* Remove it first to prevent circular derefs */
84: if (prev) prev->next = nlist->next;
85: else if (nlist->next) *fl = nlist->next;
86: else *fl = NULL;
87: if (!nlist->skipdereference) PetscObjectDereference(nlist->obj);
88: PetscFree(nlist);
89: return 0;
90: }
91: prev = nlist;
92: nlist = nlist->next;
93: }
94: return 0; /* did not find it to remove */
95: }
96: /* look for it already in list */
97: nlist = *fl;
98: while (nlist) {
99: PetscStrcmp(name,nlist->name,&match);
100: if (match) { /* found it in the list */
101: PetscObjectReference(obj);
102: if (!nlist->skipdereference) PetscObjectDereference(nlist->obj);
103: nlist->skipdereference = PETSC_FALSE;
104: nlist->obj = obj;
105: return 0;
106: }
107: nlist = nlist->next;
108: }
110: /* add it to list, because it was not already there */
111: PetscNew(&olist);
112: olist->next = NULL;
113: olist->obj = obj;
115: PetscObjectReference(obj);
116: PetscStrcpy(olist->name,name);
118: if (!*fl) *fl = olist;
119: else { /* go to end of list */
120: nlist = *fl;
121: while (nlist->next) nlist = nlist->next;
122: nlist->next = olist;
123: }
124: return 0;
125: }
127: /*@C
128: PetscObjectListDestroy - Destroy a list of objects
130: Input Parameter:
131: . ifl - pointer to list
133: Level: developer
135: .seealso: PetscObjectListAdd(), PetscObjectListFind(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate()
137: @*/
138: PetscErrorCode PetscObjectListDestroy(PetscObjectList *ifl)
139: {
140: PetscObjectList tmp,fl;
143: fl = *ifl;
144: while (fl) {
145: tmp = fl->next;
146: if (!fl->skipdereference) PetscObjectDereference(fl->obj);
147: PetscFree(fl);
148: fl = tmp;
149: }
150: *ifl = NULL;
151: return 0;
152: }
154: /*@C
155: PetscObjectListFind - givn a name, find the matching object
157: Input Parameters:
158: + fl - pointer to list
159: - name - name string
161: Output Parameters:
162: . obj - the PETSc object
164: Level: developer
166: Notes:
167: The name must have been registered with the PetscObjectListAdd() before calling this routine.
169: The reference count of the object is not increased
171: .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate()
173: @*/
174: PetscErrorCode PetscObjectListFind(PetscObjectList fl,const char name[],PetscObject *obj)
175: {
177: *obj = NULL;
178: while (fl) {
179: PetscBool match;
180: PetscStrcmp(name,fl->name,&match);
181: if (match) {
182: *obj = fl->obj;
183: break;
184: }
185: fl = fl->next;
186: }
187: return 0;
188: }
190: /*@C
191: PetscObjectListReverseFind - given a object, find the matching name if it exists
193: Input Parameters:
194: + fl - pointer to list
195: - obj - the PETSc object
197: Output Parameters:
198: + name - name string
199: - skipdereference - if the object is in list but does not have the increased reference count for a circular dependency
201: Level: developer
203: Notes:
204: The name must have been registered with the PetscObjectListAdd() before calling this routine.
206: The reference count of the object is not increased
208: .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListFind(), PetscObjectListDuplicate()
210: @*/
211: PetscErrorCode PetscObjectListReverseFind(PetscObjectList fl,PetscObject obj,char **name,PetscBool *skipdereference)
212: {
215: *name = NULL;
216: while (fl) {
217: if (fl->obj == obj) {
218: *name = fl->name;
219: if (skipdereference) *skipdereference = fl->skipdereference;
220: break;
221: }
222: fl = fl->next;
223: }
224: return 0;
225: }
227: /*@C
228: PetscObjectListDuplicate - Creates a new list from a given object list.
230: Input Parameters:
231: . fl - pointer to list
233: Output Parameters:
234: . nl - the new list (should point to 0 to start, otherwise appends)
236: Level: developer
238: .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListReverseFind(), PetscObjectListFind(), PetscObjectListDuplicate()
240: @*/
241: PetscErrorCode PetscObjectListDuplicate(PetscObjectList fl,PetscObjectList *nl)
242: {
244: while (fl) {
245: PetscObjectListAdd(nl,fl->name,fl->obj);
246: fl = fl->next;
247: }
248: return 0;
249: }