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