1
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>
7
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 };
14
15 /*@C
16 PetscObjectListRemoveReference - Calls PetscObjectDereference() on an object in the list immediately but keeps a pointer to the object in the list.
17
18 Input Parameters:
19 + fl - the object list
20 - name - the name to use for the object
21
22 Level: developer
23
24 Notes:
25 Use PetscObjectListAdd(PetscObjectList,const char name[],NULL) to truly remove the object from the list
26
27 Use this routine ONLY if you know that the object referenced will remain in existence until the pointing object is destroyed
28
29 Developer Note: this is to handle some cases that otherwise would result in having circular references so reference counts never got to zero
30
31 .seealso: PetscObjectListDestroy(), PetscObjectListFind(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate(), PetscObjectListAdd()
32
33 @*/
PetscObjectListRemoveReference(PetscObjectList * fl,const char name[])34 PetscErrorCode PetscObjectListRemoveReference(PetscObjectList *fl,const char name[])
35 {
36 PetscObjectList nlist;
37 PetscErrorCode ierr;
38 PetscBool match;
39
40 PetscFunctionBegin;
41 nlist = *fl;
42 while (nlist) {
43 ierr = PetscStrcmp(name,nlist->name,&match);CHKERRQ(ierr);
44 if (match) { /* found it in the list */
45 if (!nlist->skipdereference) {
46 ierr = PetscObjectDereference(nlist->obj);CHKERRQ(ierr);
47 }
48 nlist->skipdereference = PETSC_TRUE;
49 PetscFunctionReturn(0);
50 }
51 nlist = nlist->next;
52 }
53 PetscFunctionReturn(0);
54 }
55
56 /*@C
57 PetscObjectListAdd - Adds a new object to an PetscObjectList
58
59 Input Parameters:
60 + fl - the object list
61 . name - the name to use for the object
62 - obj - the object to attach
63
64 Level: developer
65
66 Notes:
67 Replaces item if it is already in list. Removes item if you pass in a NULL object.
68
69 Use PetscObjectListFind() or PetscObjectListReverseFind() to get the object back
70
71 .seealso: PetscObjectListDestroy(), PetscObjectListFind(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate()
72
73 @*/
PetscObjectListAdd(PetscObjectList * fl,const char name[],PetscObject obj)74 PetscErrorCode PetscObjectListAdd(PetscObjectList *fl,const char name[],PetscObject obj)
75 {
76 PetscObjectList olist,nlist,prev;
77 PetscErrorCode ierr;
78 PetscBool match;
79
80 PetscFunctionBegin;
81 if (!obj) { /* this means remove from list if it is there */
82 nlist = *fl; prev = NULL;
83 while (nlist) {
84 ierr = PetscStrcmp(name,nlist->name,&match);CHKERRQ(ierr);
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 ierr = PetscObjectDereference(nlist->obj);CHKERRQ(ierr);
92 }
93 ierr = PetscFree(nlist);CHKERRQ(ierr);
94 PetscFunctionReturn(0);
95 }
96 prev = nlist;
97 nlist = nlist->next;
98 }
99 PetscFunctionReturn(0); /* did not find it to remove */
100 }
101 /* look for it already in list */
102 nlist = *fl;
103 while (nlist) {
104 ierr = PetscStrcmp(name,nlist->name,&match);CHKERRQ(ierr);
105 if (match) { /* found it in the list */
106 ierr = PetscObjectReference(obj);CHKERRQ(ierr);
107 if (!nlist->skipdereference) {
108 ierr = PetscObjectDereference(nlist->obj);CHKERRQ(ierr);
109 }
110 nlist->skipdereference = PETSC_FALSE;
111 nlist->obj = obj;
112 PetscFunctionReturn(0);
113 }
114 nlist = nlist->next;
115 }
116
117 /* add it to list, because it was not already there */
118 ierr = PetscNew(&olist);CHKERRQ(ierr);
119 olist->next = NULL;
120 olist->obj = obj;
121
122 ierr = PetscObjectReference(obj);CHKERRQ(ierr);
123 ierr = PetscStrcpy(olist->name,name);CHKERRQ(ierr);
124
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 PetscFunctionReturn(0);
134 }
135
136 /*@C
137 PetscObjectListDestroy - Destroy a list of objects
138
139 Input Parameter:
140 . ifl - pointer to list
141
142 Level: developer
143
144 .seealso: PetscObjectListAdd(), PetscObjectListFind(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate()
145
146 @*/
PetscObjectListDestroy(PetscObjectList * ifl)147 PetscErrorCode PetscObjectListDestroy(PetscObjectList *ifl)
148 {
149 PetscObjectList tmp,fl = *ifl;
150 PetscErrorCode ierr;
151
152 PetscFunctionBegin;
153 while (fl) {
154 tmp = fl->next;
155 if (!fl->skipdereference) {
156 ierr = PetscObjectDereference(fl->obj);CHKERRQ(ierr);
157 }
158 ierr = PetscFree(fl);CHKERRQ(ierr);
159 fl = tmp;
160 }
161 *ifl = NULL;
162 PetscFunctionReturn(0);
163 }
164
165
166 /*@C
167 PetscObjectListFind - givn a name, find the matching object
168
169 Input Parameters:
170 + fl - pointer to list
171 - name - name string
172
173 Output Parameters:
174 . obj - the PETSc object
175
176 Level: developer
177
178 Notes:
179 The name must have been registered with the PetscObjectListAdd() before calling this routine.
180
181 The reference count of the object is not increased
182
183 .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate()
184
185 @*/
PetscObjectListFind(PetscObjectList fl,const char name[],PetscObject * obj)186 PetscErrorCode PetscObjectListFind(PetscObjectList fl,const char name[],PetscObject *obj)
187 {
188 PetscErrorCode ierr;
189 PetscBool match;
190
191 PetscFunctionBegin;
192 *obj = NULL;
193 while (fl) {
194 ierr = PetscStrcmp(name,fl->name,&match);CHKERRQ(ierr);
195 if (match) {
196 *obj = fl->obj;
197 break;
198 }
199 fl = fl->next;
200 }
201 PetscFunctionReturn(0);
202 }
203
204 /*@C
205 PetscObjectListReverseFind - given a object, find the matching name if it exists
206
207 Input Parameters:
208 + fl - pointer to list
209 - obj - the PETSc object
210
211 Output Parameters:
212 + name - name string
213 - skipdereference - if the object is in list but does not have the increased reference count for a circular dependency
214
215 Level: developer
216
217 Notes:
218 The name must have been registered with the PetscObjectListAdd() before calling this routine.
219
220 The reference count of the object is not increased
221
222 .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListFind(), PetscObjectListDuplicate()
223
224 @*/
PetscObjectListReverseFind(PetscObjectList fl,PetscObject obj,char ** name,PetscBool * skipdereference)225 PetscErrorCode PetscObjectListReverseFind(PetscObjectList fl,PetscObject obj,char **name,PetscBool *skipdereference)
226 {
227 PetscFunctionBegin;
228 *name = NULL;
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 PetscFunctionReturn(0);
238 }
239
240 /*@C
241 PetscObjectListDuplicate - Creates a new list from a given object list.
242
243 Input Parameters:
244 . fl - pointer to list
245
246 Output Parameters:
247 . nl - the new list (should point to 0 to start, otherwise appends)
248
249 Level: developer
250
251 .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListReverseFind(), PetscObjectListFind(), PetscObjectListDuplicate()
252
253 @*/
PetscObjectListDuplicate(PetscObjectList fl,PetscObjectList * nl)254 PetscErrorCode PetscObjectListDuplicate(PetscObjectList fl,PetscObjectList *nl)
255 {
256 PetscErrorCode ierr;
257
258 PetscFunctionBegin;
259 while (fl) {
260 ierr = PetscObjectListAdd(nl,fl->name,fl->obj);CHKERRQ(ierr);
261 fl = fl->next;
262 }
263 PetscFunctionReturn(0);
264 }
265