Actual source code: olist.c
petsc-3.11.4 2019-09-28
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 = 0;
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 = 0;
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 = 0;
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: }
166: /*@C
167: PetscObjectListFind - givn a name, find the matching object
169: Input Parameters:
170: + fl - pointer to list
171: - name - name string
173: Output Parameters:
174: . ob - the PETSc object
176: Level: developer
178: Notes:
179: The name must have been registered with the PetscObjectListAdd() before calling this routine.
181: The reference count of the object is not increased
183: .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate()
185: @*/
186: PetscErrorCode PetscObjectListFind(PetscObjectList fl,const char name[],PetscObject *obj)
187: {
189: PetscBool match;
192: *obj = 0;
193: while (fl) {
194: PetscStrcmp(name,fl->name,&match);
195: if (match) {
196: *obj = fl->obj;
197: break;
198: }
199: fl = fl->next;
200: }
201: return(0);
202: }
204: /*@C
205: PetscObjectListReverseFind - given a object, find the matching name if it exists
207: Input Parameters:
208: + fl - pointer to list
209: - ob - the PETSc object
211: Output Parameters:
212: + name - name string
213: - skipdereference - if the object is list but does not have the increased reference count for a circular dependency
215: Level: developer
217: Notes:
218: The name must have been registered with the PetscObjectListAdd() before calling this routine.
220: The reference count of the object is not increased
222: .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListFind(), PetscObjectListDuplicate()
224: @*/
225: PetscErrorCode PetscObjectListReverseFind(PetscObjectList fl,PetscObject obj,char **name,PetscBool *skipdereference)
226: {
228: *name = 0;
229: while (fl) {
230: if (fl->obj == obj) {
231: *name = fl->name;
232: if (skipdereference) *skipdereference = fl->skipdereference;
233: break;
234: }
235: fl = fl->next;
236: }
237: return(0);
238: }
240: /*@C
241: PetscObjectListDuplicate - Creates a new list from a give object list.
243: Input Parameters:
244: . fl - pointer to list
246: Output Parameters:
247: . nl - the new list (should point to 0 to start, otherwise appends)
249: Level: developer
251: .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListReverseFind(), PetscObjectListFind(), PetscObjectListDuplicate()
253: @*/
254: PetscErrorCode PetscObjectListDuplicate(PetscObjectList fl,PetscObjectList *nl)
255: {
259: while (fl) {
260: PetscObjectListAdd(nl,fl->name,fl->obj);
261: fl = fl->next;
262: }
263: return(0);
264: }