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