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