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:
30: 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()`
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()`
70: @*/
71: PetscErrorCode PetscObjectListAdd(PetscObjectList *fl, const char name[], PetscObject obj)
72: {
73: PetscObjectList olist, nlist, prev;
74: PetscBool match;
77: if (!obj) { /* this means remove from list if it is there */
78: nlist = *fl;
79: 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 */ nlist = *fl;
120: while (nlist->next) nlist = nlist->next;
121: nlist->next = olist;
122: }
123: return 0;
124: }
126: /*@C
127: PetscObjectListDestroy - Destroy a list of objects
129: Input Parameter:
130: . ifl - pointer to list
132: Level: developer
134: .seealso: `PetscObjectListAdd()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()`, `PetscObjectListReverseFind()`, `PetscObjectListDuplicate()`
135: @*/
136: PetscErrorCode PetscObjectListDestroy(PetscObjectList *ifl)
137: {
138: PetscObjectList tmp, fl;
141: fl = *ifl;
142: while (fl) {
143: tmp = fl->next;
144: if (!fl->skipdereference) PetscObjectDereference(fl->obj);
145: PetscFree(fl);
146: fl = tmp;
147: }
148: *ifl = NULL;
149: return 0;
150: }
152: /*@C
153: PetscObjectListFind - givn a name, find the matching object
155: Input Parameters:
156: + fl - pointer to list
157: - name - name string
159: Output Parameters:
160: . obj - the PETSc object
162: Level: developer
164: Notes:
165: The name must have been registered with the `PetscObjectListAdd()` before calling this routine.
167: The reference count of the object is not increased
169: .seealso: `PetscObjectListDestroy()`, `PetscObjectListAdd()`, `PetscObjectListDuplicate()`, `PetscObjectListReverseFind()`, `PetscObjectListDuplicate()`
170: @*/
171: PetscErrorCode PetscObjectListFind(PetscObjectList fl, const char name[], PetscObject *obj)
172: {
174: *obj = NULL;
175: while (fl) {
176: PetscBool match;
177: PetscStrcmp(name, fl->name, &match);
178: if (match) {
179: *obj = fl->obj;
180: break;
181: }
182: fl = fl->next;
183: }
184: return 0;
185: }
187: /*@C
188: PetscObjectListReverseFind - given a object, find the matching name if it exists
190: Input Parameters:
191: + fl - pointer to list
192: - obj - the PETSc object
194: Output Parameters:
195: + name - name string
196: - skipdereference - if the object is in list but does not have the increased reference count for a circular dependency
198: Level: developer
200: Notes:
201: The name must have been registered with the `PetscObjectListAdd()` before calling this routine.
203: The reference count of the object is not increased
205: .seealso: `PetscObjectListDestroy()`, `PetscObjectListAdd()`, `PetscObjectListDuplicate()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()`
206: @*/
207: PetscErrorCode PetscObjectListReverseFind(PetscObjectList fl, PetscObject obj, char **name, PetscBool *skipdereference)
208: {
211: *name = NULL;
212: while (fl) {
213: if (fl->obj == obj) {
214: *name = fl->name;
215: if (skipdereference) *skipdereference = fl->skipdereference;
216: break;
217: }
218: fl = fl->next;
219: }
220: return 0;
221: }
223: /*@C
224: PetscObjectListDuplicate - Creates a new list from a given object list.
226: Input Parameters:
227: . fl - pointer to list
229: Output Parameters:
230: . nl - the new list (should point to 0 to start, otherwise appends)
232: Level: developer
234: .seealso: `PetscObjectListDestroy()`, `PetscObjectListAdd()`, `PetscObjectListReverseFind()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()`
235: @*/
236: PetscErrorCode PetscObjectListDuplicate(PetscObjectList fl, PetscObjectList *nl)
237: {
239: while (fl) {
240: PetscObjectListAdd(nl, fl->name, fl->obj);
241: fl = fl->next;
242: }
243: return 0;
244: }