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