xref: /petsc/src/sys/objects/olist.c (revision 030f984af8d8bb4c203755d35bded3c05b3d83ce)
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 /*@C
16      PetscObjectListRemoveReference - Calls PetscObjectDereference() on an object in the list immediately but keeps a pointer to the object in the list.
17 
18     Input Parameters:
19 +     fl - the object list
20 -     name - the name to use for the object
21 
22     Level: developer
23 
24        Notes:
25     Use PetscObjectListAdd(PetscObjectList,const char name[],NULL) to truly remove the object from the list
26 
27               Use this routine ONLY if you know that the object referenced will remain in existence until the pointing object is destroyed
28 
29       Developer Note: this is to handle some cases that otherwise would result in having circular references so reference counts never got to zero
30 
31 .seealso: PetscObjectListDestroy(), PetscObjectListFind(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate(), PetscObjectListAdd()
32 
33 @*/
34 PetscErrorCode  PetscObjectListRemoveReference(PetscObjectList *fl,const char name[])
35 {
36   PetscObjectList nlist;
37   PetscErrorCode  ierr;
38   PetscBool       match;
39 
40   PetscFunctionBegin;
41   nlist = *fl;
42   while (nlist) {
43     ierr = PetscStrcmp(name,nlist->name,&match);CHKERRQ(ierr);
44     if (match) { /* found it in the list */
45       if (!nlist->skipdereference) {
46         ierr = PetscObjectDereference(nlist->obj);CHKERRQ(ierr);
47       }
48       nlist->skipdereference = PETSC_TRUE;
49       PetscFunctionReturn(0);
50     }
51     nlist = nlist->next;
52   }
53   PetscFunctionReturn(0);
54 }
55 
56 /*@C
57      PetscObjectListAdd - Adds a new object to an PetscObjectList
58 
59     Input Parameters:
60 +     fl - the object list
61 .     name - the name to use for the object
62 -     obj - the object to attach
63 
64     Level: developer
65 
66        Notes:
67     Replaces item if it is already in list. Removes item if you pass in a NULL object.
68 
69         Use PetscObjectListFind() or PetscObjectListReverseFind() to get the object back
70 
71 .seealso: PetscObjectListDestroy(), PetscObjectListFind(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate()
72 
73 @*/
74 PetscErrorCode  PetscObjectListAdd(PetscObjectList *fl,const char name[],PetscObject obj)
75 {
76   PetscObjectList olist,nlist,prev;
77   PetscErrorCode  ierr;
78   PetscBool       match;
79 
80   PetscFunctionBegin;
81   if (!obj) { /* this means remove from list if it is there */
82     nlist = *fl; prev = NULL;
83     while (nlist) {
84       ierr = PetscStrcmp(name,nlist->name,&match);CHKERRQ(ierr);
85       if (match) {  /* found it already in the list */
86         /* Remove it first to prevent circular derefs */
87         if (prev) prev->next = nlist->next;
88         else if (nlist->next) *fl = nlist->next;
89         else *fl = NULL;
90         if (!nlist->skipdereference) {
91           ierr = PetscObjectDereference(nlist->obj);CHKERRQ(ierr);
92         }
93         ierr = PetscFree(nlist);CHKERRQ(ierr);
94         PetscFunctionReturn(0);
95       }
96       prev  = nlist;
97       nlist = nlist->next;
98     }
99     PetscFunctionReturn(0); /* did not find it to remove */
100   }
101   /* look for it already in list */
102   nlist = *fl;
103   while (nlist) {
104     ierr = PetscStrcmp(name,nlist->name,&match);CHKERRQ(ierr);
105     if (match) {  /* found it in the list */
106       ierr = PetscObjectReference(obj);CHKERRQ(ierr);
107       if (!nlist->skipdereference) {
108         ierr = PetscObjectDereference(nlist->obj);CHKERRQ(ierr);
109       }
110       nlist->skipdereference = PETSC_FALSE;
111       nlist->obj             = obj;
112       PetscFunctionReturn(0);
113     }
114     nlist = nlist->next;
115   }
116 
117   /* add it to list, because it was not already there */
118   ierr        = PetscNew(&olist);CHKERRQ(ierr);
119   olist->next = NULL;
120   olist->obj  = obj;
121 
122   ierr = PetscObjectReference(obj);CHKERRQ(ierr);
123   ierr = PetscStrcpy(olist->name,name);CHKERRQ(ierr);
124 
125   if (!*fl) *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 /*@C
137     PetscObjectListDestroy - Destroy a list of objects
138 
139     Input Parameter:
140 .   ifl   - pointer to list
141 
142     Level: developer
143 
144 .seealso: PetscObjectListAdd(), PetscObjectListFind(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate()
145 
146 @*/
147 PetscErrorCode  PetscObjectListDestroy(PetscObjectList *ifl)
148 {
149   PetscObjectList tmp,fl = *ifl;
150   PetscErrorCode  ierr;
151 
152   PetscFunctionBegin;
153   while (fl) {
154     tmp = fl->next;
155     if (!fl->skipdereference) {
156       ierr = PetscObjectDereference(fl->obj);CHKERRQ(ierr);
157     }
158     ierr = PetscFree(fl);CHKERRQ(ierr);
159     fl   = tmp;
160   }
161   *ifl = NULL;
162   PetscFunctionReturn(0);
163 }
164 
165 /*@C
166     PetscObjectListFind - givn a name, find the matching object
167 
168     Input Parameters:
169 +   fl   - pointer to list
170 -   name - name string
171 
172     Output Parameters:
173 .   obj - the PETSc object
174 
175     Level: developer
176 
177     Notes:
178     The name must have been registered with the PetscObjectListAdd() before calling this routine.
179 
180     The reference count of the object is not increased
181 
182 .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate()
183 
184 @*/
185 PetscErrorCode  PetscObjectListFind(PetscObjectList fl,const char name[],PetscObject *obj)
186 {
187   PetscErrorCode ierr;
188   PetscBool      match;
189 
190   PetscFunctionBegin;
191   *obj = NULL;
192   while (fl) {
193     ierr = PetscStrcmp(name,fl->name,&match);CHKERRQ(ierr);
194     if (match) {
195       *obj = fl->obj;
196       break;
197     }
198     fl = fl->next;
199   }
200   PetscFunctionReturn(0);
201 }
202 
203 /*@C
204     PetscObjectListReverseFind - given a object, find the matching name if it exists
205 
206     Input Parameters:
207 +   fl   - pointer to list
208 -   obj - the PETSc object
209 
210     Output Parameters:
211 +  name - name string
212 -  skipdereference - if the object is in list but does not have the increased reference count for a circular dependency
213 
214     Level: developer
215 
216     Notes:
217     The name must have been registered with the PetscObjectListAdd() before calling this routine.
218 
219     The reference count of the object is not increased
220 
221 .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListFind(), PetscObjectListDuplicate()
222 
223 @*/
224 PetscErrorCode  PetscObjectListReverseFind(PetscObjectList fl,PetscObject obj,char **name,PetscBool *skipdereference)
225 {
226   PetscFunctionBegin;
227   *name = NULL;
228   while (fl) {
229     if (fl->obj == obj) {
230       *name = fl->name;
231       if (skipdereference) *skipdereference = fl->skipdereference;
232       break;
233     }
234     fl = fl->next;
235   }
236   PetscFunctionReturn(0);
237 }
238 
239 /*@C
240     PetscObjectListDuplicate - Creates a new list from a given object list.
241 
242     Input Parameters:
243 .   fl   - pointer to list
244 
245     Output Parameters:
246 .   nl - the new list (should point to 0 to start, otherwise appends)
247 
248     Level: developer
249 
250 .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListReverseFind(), PetscObjectListFind(), PetscObjectListDuplicate()
251 
252 @*/
253 PetscErrorCode  PetscObjectListDuplicate(PetscObjectList fl,PetscObjectList *nl)
254 {
255   PetscErrorCode ierr;
256 
257   PetscFunctionBegin;
258   while (fl) {
259     ierr = PetscObjectListAdd(nl,fl->name,fl->obj);CHKERRQ(ierr);
260     fl   = fl->next;
261   }
262   PetscFunctionReturn(0);
263 }
264