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