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