Actual source code: olist.c
petsc-3.9.4 2018-09-11
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: Use PetscObjectListAdd(PetscObjectList,const char name[],NULL) to truly remove the object from the list
26: Use this routine ONLY if you know that the object referenced will remain in existence until the pointing object is destroyed
28: Developer Note: this is to handle some cases that otherwise would result in having circular references so reference counts never got to zero
30: .seealso: PetscObjectListDestroy(), PetscObjectListFind(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate(), PetscObjectListAdd()
32: @*/
33: PetscErrorCode PetscObjectListRemoveReference(PetscObjectList *fl,const char name[])
34: {
35: PetscObjectList nlist;
36: PetscErrorCode ierr;
37: PetscBool match;
40: nlist = *fl;
41: while (nlist) {
42: PetscStrcmp(name,nlist->name,&match);
43: if (match) { /* found it in the list */
44: if (!nlist->skipdereference) {
45: PetscObjectDereference(nlist->obj);
46: }
47: nlist->skipdereference = PETSC_TRUE;
48: return(0);
49: }
50: nlist = nlist->next;
51: }
52: return(0);
53: }
55: /*@C
56: PetscObjectListAdd - Adds a new object to an PetscObjectList
58: Input Parameters:
59: + fl - the object list
60: . name - the name to use for the object
61: - obj - the object to attach
63: Level: developer
65: Notes: 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: PetscErrorCode ierr;
76: PetscBool match;
79: if (!obj) { /* this means remove from list if it is there */
80: nlist = *fl; prev = 0;
81: while (nlist) {
82: PetscStrcmp(name,nlist->name,&match);
83: if (match) { /* found it already in the list */
84: /* Remove it first to prevent circular derefs */
85: if (prev) prev->next = nlist->next;
86: else if (nlist->next) *fl = nlist->next;
87: else *fl = 0;
88: if (!nlist->skipdereference) {
89: PetscObjectDereference(nlist->obj);
90: }
91: PetscFree(nlist);
92: return(0);
93: }
94: prev = nlist;
95: nlist = nlist->next;
96: }
97: return(0); /* did not find it to remove */
98: }
99: /* look for it already in list */
100: nlist = *fl;
101: while (nlist) {
102: PetscStrcmp(name,nlist->name,&match);
103: if (match) { /* found it in the list */
104: PetscObjectReference(obj);
105: if (!nlist->skipdereference) {
106: PetscObjectDereference(nlist->obj);
107: }
108: nlist->skipdereference = PETSC_FALSE;
109: nlist->obj = obj;
110: return(0);
111: }
112: nlist = nlist->next;
113: }
115: /* add it to list, because it was not already there */
116: PetscNew(&olist);
117: olist->next = 0;
118: olist->obj = obj;
120: PetscObjectReference(obj);
121: PetscStrcpy(olist->name,name);
123: if (!*fl) *fl = olist;
124: else { /* go to end of list */
125: nlist = *fl;
126: while (nlist->next) {
127: nlist = nlist->next;
128: }
129: nlist->next = olist;
130: }
131: return(0);
132: }
134: /*@C
135: PetscObjectListDestroy - Destroy a list of objects
137: Input Parameter:
138: . ifl - pointer to list
140: Level: developer
142: .seealso: PetscObjectListAdd(), PetscObjectListFind(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate()
144: @*/
145: PetscErrorCode PetscObjectListDestroy(PetscObjectList *ifl)
146: {
147: PetscObjectList tmp,fl = *ifl;
148: PetscErrorCode ierr;
151: while (fl) {
152: tmp = fl->next;
153: if (!fl->skipdereference) {
154: PetscObjectDereference(fl->obj);
155: }
156: PetscFree(fl);
157: fl = tmp;
158: }
159: *ifl = NULL;
160: return(0);
161: }
164: /*@C
165: PetscObjectListFind - givn a name, find the matching object
167: Input Parameters:
168: + fl - pointer to list
169: - name - name string
171: Output Parameters:
172: . ob - the PETSc object
174: Level: developer
176: Notes:
177: The name must have been registered with the PetscObjectListAdd() before calling this routine.
179: The reference count of the object is not increased
181: .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate()
183: @*/
184: PetscErrorCode PetscObjectListFind(PetscObjectList fl,const char name[],PetscObject *obj)
185: {
187: PetscBool match;
190: *obj = 0;
191: while (fl) {
192: PetscStrcmp(name,fl->name,&match);
193: if (match) {
194: *obj = fl->obj;
195: break;
196: }
197: fl = fl->next;
198: }
199: return(0);
200: }
202: /*@C
203: PetscObjectListReverseFind - given a object, find the matching name if it exists
205: Input Parameters:
206: + fl - pointer to list
207: - ob - the PETSc object
209: Output Parameters:
210: + name - name string
211: - skipdereference - if the object is list but does not have the increased reference count for a circular dependency
213: Level: developer
215: Notes:
216: The name must have been registered with the PetscObjectListAdd() before calling this routine.
218: The reference count of the object is not increased
220: .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListFind(), PetscObjectListDuplicate()
222: @*/
223: PetscErrorCode PetscObjectListReverseFind(PetscObjectList fl,PetscObject obj,char **name,PetscBool *skipdereference)
224: {
226: *name = 0;
227: while (fl) {
228: if (fl->obj == obj) {
229: *name = fl->name;
230: if (skipdereference) *skipdereference = fl->skipdereference;
231: break;
232: }
233: fl = fl->next;
234: }
235: return(0);
236: }
238: /*@C
239: PetscObjectListDuplicate - Creates a new list from a give object list.
241: Input Parameters:
242: . fl - pointer to list
244: Output Parameters:
245: . nl - the new list (should point to 0 to start, otherwise appends)
247: Level: developer
249: .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListReverseFind(), PetscObjectListFind(), PetscObjectListDuplicate()
251: @*/
252: PetscErrorCode PetscObjectListDuplicate(PetscObjectList fl,PetscObjectList *nl)
253: {
257: while (fl) {
258: PetscObjectListAdd(nl,fl->name,fl->obj);
259: fl = fl->next;
260: }
261: return(0);
262: }