xref: /petsc/src/sys/objects/olist.c (revision 6e111a19f6677190c8cb13236301fcb65e0e3d3b)
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[],PETSC_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 PETSC_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         if (!nlist->skipdereference) {
89           ierr = PetscObjectDereference(nlist->obj);CHKERRQ(ierr);
90         }
91         if (prev) prev->next = nlist->next;
92         else if (nlist->next) {
93           *fl = nlist->next;
94         } else {
95           *fl = 0;
96         }
97         ierr = PetscFree(nlist);CHKERRQ(ierr);
98         PetscFunctionReturn(0);
99       }
100       prev  = nlist;
101       nlist = nlist->next;
102     }
103     PetscFunctionReturn(0); /* did not find it to remove */
104   }
105   /* look for it already in list */
106   nlist = *fl;
107   while (nlist) {
108     ierr = PetscStrcmp(name,nlist->name,&match);CHKERRQ(ierr);
109     if (match) {  /* found it in the list */
110       ierr = PetscObjectReference(obj);CHKERRQ(ierr);
111       if (!nlist->skipdereference) {
112         ierr = PetscObjectDereference(nlist->obj);CHKERRQ(ierr);
113       }
114       nlist->skipdereference = PETSC_FALSE;
115       nlist->obj             = obj;
116       PetscFunctionReturn(0);
117     }
118     nlist = nlist->next;
119   }
120 
121   /* add it to list, because it was not already there */
122   ierr        = PetscNew(struct _n_PetscObjectList,&olist);CHKERRQ(ierr);
123   olist->next = 0;
124   olist->obj  = obj;
125   ierr = PetscObjectReference(obj);CHKERRQ(ierr);
126   ierr = PetscStrcpy(olist->name,name);CHKERRQ(ierr);
127 
128   if (!*fl) {
129     *fl = olist;
130   } else { /* go to end of list */
131     nlist = *fl;
132     while (nlist->next) {
133       nlist = nlist->next;
134     }
135     nlist->next = olist;
136   }
137   PetscFunctionReturn(0);
138 }
139 
140 #undef __FUNCT__
141 #define __FUNCT__ "PetscObjectListDestroy"
142 /*@C
143     PetscObjectListDestroy - Destroy a list of objects
144 
145     Input Parameter:
146 .   ifl   - pointer to list
147 
148     Level: developer
149 
150 .seealso: PetscObjectListAdd(), PetscObjectListFind(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate()
151 
152 @*/
153 PetscErrorCode  PetscObjectListDestroy(PetscObjectList *ifl)
154 {
155   PetscObjectList tmp,fl = *ifl;
156   PetscErrorCode  ierr;
157 
158   PetscFunctionBegin;
159   while (fl) {
160     tmp   = fl->next;
161     if (!fl->skipdereference) {
162       ierr  = PetscObjectDereference(fl->obj);CHKERRQ(ierr);
163     }
164     ierr  = PetscFree(fl);CHKERRQ(ierr);
165     fl    = tmp;
166   }
167   *ifl = PETSC_NULL;
168   PetscFunctionReturn(0);
169 }
170 
171 
172 #undef __FUNCT__
173 #define __FUNCT__ "PetscObjectListFind"
174 /*@C
175     PetscObjectListFind - givn a name, find the matching object
176 
177     Input Parameters:
178 +   fl   - pointer to list
179 -   name - name string
180 
181     Output Parameters:
182 .   ob - the PETSc object
183 
184     Level: developer
185 
186     Notes:
187     The name must have been registered with the PetscObjectListAdd() before calling this routine.
188 
189     The reference count of the object is not increased
190 
191 .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate()
192 
193 @*/
194 PetscErrorCode  PetscObjectListFind(PetscObjectList fl,const char name[],PetscObject *obj)
195 {
196   PetscErrorCode ierr;
197   PetscBool      match;
198 
199   PetscFunctionBegin;
200   *obj = 0;
201   while (fl) {
202     ierr = PetscStrcmp(name,fl->name,&match);CHKERRQ(ierr);
203     if (match) {
204       *obj = fl->obj;
205       break;
206     }
207     fl = fl->next;
208   }
209   PetscFunctionReturn(0);
210 }
211 
212 #undef __FUNCT__
213 #define __FUNCT__ "PetscObjectListReverseFind"
214 /*@C
215     PetscObjectListReverseFind - given a object, find the matching name if it exists
216 
217     Input Parameters:
218 +   fl   - pointer to list
219 -   ob - the PETSc object
220 
221     Output Parameters:
222 +  name - name string
223 -  skipdereference - if the object is list but does not have the increased reference count for a circular dependency
224 
225     Level: developer
226 
227     Notes:
228     The name must have been registered with the PetscObjectListAdd() before calling this routine.
229 
230     The reference count of the object is not increased
231 
232 .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListFind(), PetscObjectListDuplicate()
233 
234 @*/
235 PetscErrorCode  PetscObjectListReverseFind(PetscObjectList fl,PetscObject obj,char **name,PetscBool *skipdereference)
236 {
237   PetscFunctionBegin;
238   *name = 0;
239   while (fl) {
240     if (fl->obj == obj) {
241       *name = fl->name;
242       if (skipdereference) *skipdereference = fl->skipdereference;
243       break;
244     }
245     fl = fl->next;
246   }
247   PetscFunctionReturn(0);
248 }
249 
250 #undef __FUNCT__
251 #define __FUNCT__ "PetscObjectListDuplicate"
252 /*@C
253     PetscObjectListDuplicate - Creates a new list from a give object list.
254 
255     Input Parameters:
256 .   fl   - pointer to list
257 
258     Output Parameters:
259 .   nl - the new list (should point to 0 to start, otherwise appends)
260 
261     Level: developer
262 
263 .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListReverseFind(), PetscObjectListFind(), PetscObjectListDuplicate()
264 
265 @*/
266 PetscErrorCode  PetscObjectListDuplicate(PetscObjectList fl,PetscObjectList *nl)
267 {
268   PetscErrorCode ierr;
269 
270   PetscFunctionBegin;
271   while (fl) {
272     ierr = PetscObjectListAdd(nl,fl->name,fl->obj);CHKERRQ(ierr);
273     fl = fl->next;
274   }
275   PetscFunctionReturn(0);
276 }
277 
278 
279 
280 
281 
282