xref: /petsc/src/sys/objects/olist.c (revision 84df9cb40eca90ea9b18a456fab7a4ecc7f6c1a4)
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 -  skipdereference - if the object is list but does not have the increased reference count for a circular dependency
225 
226     Level: developer
227 
228     Notes:
229     The name must have been registered with the PetscOListAdd() before calling this routine.
230 
231     The reference count of the object is not increased
232 
233 .seealso: PetscOListDestroy(), PetscOListAdd(), PetscOListDuplicate(), PetscOListFind(), PetscOListDuplicate()
234 
235 @*/
236 PetscErrorCode  PetscOListReverseFind(PetscOList fl,PetscObject obj,char **name,PetscBool *skipdereference)
237 {
238   PetscFunctionBegin;
239   *name = 0;
240   while (fl) {
241     if (fl->obj == obj) {
242       *name = fl->name;
243       if (skipdereference) *skipdereference = fl->skipdereference;
244       break;
245     }
246     fl = fl->next;
247   }
248   PetscFunctionReturn(0);
249 }
250 
251 #undef __FUNCT__
252 #define __FUNCT__ "PetscOListDuplicate"
253 /*@C
254     PetscOListDuplicate - Creates a new list from a give object list.
255 
256     Input Parameters:
257 .   fl   - pointer to list
258 
259     Output Parameters:
260 .   nl - the new list (should point to 0 to start, otherwise appends)
261 
262     Level: developer
263 
264 .seealso: PetscOListDestroy(), PetscOListAdd(), PetscOListReverseFind(), PetscOListFind(), PetscOListDuplicate()
265 
266 @*/
267 PetscErrorCode  PetscOListDuplicate(PetscOList fl,PetscOList *nl)
268 {
269   PetscErrorCode ierr;
270 
271   PetscFunctionBegin;
272   while (fl) {
273     ierr = PetscOListAdd(nl,fl->name,fl->obj);CHKERRQ(ierr);
274     fl = fl->next;
275   }
276   PetscFunctionReturn(0);
277 }
278 
279 
280 
281 
282 
283