xref: /petsc/src/sys/objects/olist.c (revision 811af0c4b09a35de4306c442f88bd09fdc09897d)
17d0a6c19SBarry Smith 
2e5c89e4eSSatish Balay /*
3e5c89e4eSSatish Balay          Provides a general mechanism to maintain a linked list of PETSc objects.
4e5c89e4eSSatish Balay      This is used to allow PETSc objects to carry a list of "composed" objects
5e5c89e4eSSatish Balay */
65f80ce2aSJacob Faibussowitsch #include <petsc/private/petscimpl.h>
7e5c89e4eSSatish Balay 
8140e18c1SBarry Smith struct _n_PetscObjectList {
9e5c89e4eSSatish Balay   char            name[256];
10140e18c1SBarry Smith   PetscBool       skipdereference; /* when the PetscObjectList is destroyed do not call PetscObjectDereference() on this object */
11e5c89e4eSSatish Balay   PetscObject     obj;
12140e18c1SBarry Smith   PetscObjectList next;
13e5c89e4eSSatish Balay };
14e5c89e4eSSatish Balay 
156ba4bc90SBarry Smith /*@C
16*811af0c4SBarry Smith      PetscObjectListRemoveReference - Calls `PetscObjectDereference()` on an object in the list immediately but keeps a pointer to the object in the list.
176ba4bc90SBarry Smith 
186ba4bc90SBarry Smith     Input Parameters:
196ba4bc90SBarry Smith +     fl - the object list
206ba4bc90SBarry Smith -     name - the name to use for the object
216ba4bc90SBarry Smith 
226ba4bc90SBarry Smith     Level: developer
236ba4bc90SBarry Smith 
2495452b02SPatrick Sanan     Notes:
25*811af0c4SBarry Smith     Use `PetscObjectListAdd`(`PetscObjectList`,const char name[],NULL) to truly remove the object from the list
266ba4bc90SBarry Smith 
276ba4bc90SBarry Smith     Use this routine ONLY if you know that the object referenced will remain in existence until the pointing object is destroyed
286ba4bc90SBarry Smith 
29*811af0c4SBarry Smith     Developer Note:
30*811af0c4SBarry Smith     This is to handle some cases that otherwise would result in having circular references so reference counts never got to zero
316ba4bc90SBarry Smith 
32db781477SPatrick Sanan .seealso: `PetscObjectListDestroy()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()`, `PetscObjectListReverseFind()`, `PetscObjectListDuplicate()`, `PetscObjectListAdd()`
336ba4bc90SBarry Smith @*/
349371c9d4SSatish Balay PetscErrorCode PetscObjectListRemoveReference(PetscObjectList *fl, const char name[]) {
35140e18c1SBarry Smith   PetscObjectList nlist;
366ba4bc90SBarry Smith   PetscBool       match;
376ba4bc90SBarry Smith 
386ba4bc90SBarry Smith   PetscFunctionBegin;
395f80ce2aSJacob Faibussowitsch   PetscValidPointer(fl, 1);
405f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(name, 2);
4187130e5eSHong Zhang   nlist = *fl;
426ba4bc90SBarry Smith   while (nlist) {
439566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, nlist->name, &match));
4400ac8be1SBarry Smith     if (match) { /* found it in the list */
459566063dSJacob Faibussowitsch       if (!nlist->skipdereference) PetscCall(PetscObjectDereference(nlist->obj));
466ba4bc90SBarry Smith       nlist->skipdereference = PETSC_TRUE;
476ba4bc90SBarry Smith       PetscFunctionReturn(0);
486ba4bc90SBarry Smith     }
496ba4bc90SBarry Smith     nlist = nlist->next;
506ba4bc90SBarry Smith   }
516ba4bc90SBarry Smith   PetscFunctionReturn(0);
526ba4bc90SBarry Smith }
536ba4bc90SBarry Smith 
541d0fab5eSBarry Smith /*@C
55*811af0c4SBarry Smith      PetscObjectListAdd - Adds a new object to an `PetscObjectList`
56e5c89e4eSSatish Balay 
571d0fab5eSBarry Smith     Input Parameters:
581d0fab5eSBarry Smith +     fl - the object list
591d0fab5eSBarry Smith .     name - the name to use for the object
601d0fab5eSBarry Smith -     obj - the object to attach
61e5c89e4eSSatish Balay 
62b235ab32SBarry Smith     Level: developer
63b235ab32SBarry Smith 
6495452b02SPatrick Sanan     Notes:
6595452b02SPatrick Sanan     Replaces item if it is already in list. Removes item if you pass in a NULL object.
661d0fab5eSBarry Smith 
67*811af0c4SBarry Smith     Use `PetscObjectListFind()` or `PetscObjectListReverseFind()` to get the object back
681d0fab5eSBarry Smith 
69db781477SPatrick Sanan .seealso: `PetscObjectListDestroy()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()`, `PetscObjectListReverseFind()`, `PetscObjectListDuplicate()`
701d0fab5eSBarry Smith @*/
719371c9d4SSatish Balay PetscErrorCode PetscObjectListAdd(PetscObjectList *fl, const char name[], PetscObject obj) {
72140e18c1SBarry Smith   PetscObjectList olist, nlist, prev;
73ace3abfcSBarry Smith   PetscBool       match;
74e5c89e4eSSatish Balay 
75e5c89e4eSSatish Balay   PetscFunctionBegin;
765f80ce2aSJacob Faibussowitsch   PetscValidPointer(fl, 1);
77e5c89e4eSSatish Balay   if (!obj) { /* this means remove from list if it is there */
789371c9d4SSatish Balay     nlist = *fl;
799371c9d4SSatish Balay     prev  = NULL;
80e5c89e4eSSatish Balay     while (nlist) {
819566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, nlist->name, &match));
82e5c89e4eSSatish Balay       if (match) { /* found it already in the list */
834a0791bcSMatthew G. Knepley         /* Remove it first to prevent circular derefs */
84e5c89e4eSSatish Balay         if (prev) prev->next = nlist->next;
85a297a907SKarl Rupp         else if (nlist->next) *fl = nlist->next;
8602c9f0b5SLisandro Dalcin         else *fl = NULL;
879566063dSJacob Faibussowitsch         if (!nlist->skipdereference) PetscCall(PetscObjectDereference(nlist->obj));
889566063dSJacob Faibussowitsch         PetscCall(PetscFree(nlist));
89e5c89e4eSSatish Balay         PetscFunctionReturn(0);
90e5c89e4eSSatish Balay       }
91e5c89e4eSSatish Balay       prev  = nlist;
92e5c89e4eSSatish Balay       nlist = nlist->next;
93e5c89e4eSSatish Balay     }
94e5c89e4eSSatish Balay     PetscFunctionReturn(0); /* did not find it to remove */
95e5c89e4eSSatish Balay   }
96e5c89e4eSSatish Balay   /* look for it already in list */
97e5c89e4eSSatish Balay   nlist = *fl;
98e5c89e4eSSatish Balay   while (nlist) {
999566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, nlist->name, &match));
100e5c89e4eSSatish Balay     if (match) { /* found it in the list */
1019566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference(obj));
1029566063dSJacob Faibussowitsch       if (!nlist->skipdereference) PetscCall(PetscObjectDereference(nlist->obj));
10300ac8be1SBarry Smith       nlist->skipdereference = PETSC_FALSE;
104e5c89e4eSSatish Balay       nlist->obj             = obj;
105e5c89e4eSSatish Balay       PetscFunctionReturn(0);
106e5c89e4eSSatish Balay     }
107e5c89e4eSSatish Balay     nlist = nlist->next;
108e5c89e4eSSatish Balay   }
109e5c89e4eSSatish Balay 
110e5c89e4eSSatish Balay   /* add it to list, because it was not already there */
1119566063dSJacob Faibussowitsch   PetscCall(PetscNew(&olist));
11202c9f0b5SLisandro Dalcin   olist->next = NULL;
113e5c89e4eSSatish Balay   olist->obj  = obj;
114a297a907SKarl Rupp 
1159566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference(obj));
1169566063dSJacob Faibussowitsch   PetscCall(PetscStrcpy(olist->name, name));
117e5c89e4eSSatish Balay 
118a297a907SKarl Rupp   if (!*fl) *fl = olist;
1199371c9d4SSatish Balay   else { /* go to end of list */ nlist = *fl;
1205f80ce2aSJacob Faibussowitsch     while (nlist->next) nlist = nlist->next;
121e5c89e4eSSatish Balay     nlist->next = olist;
122e5c89e4eSSatish Balay   }
123e5c89e4eSSatish Balay   PetscFunctionReturn(0);
124e5c89e4eSSatish Balay }
125e5c89e4eSSatish Balay 
1261d0fab5eSBarry Smith /*@C
127140e18c1SBarry Smith     PetscObjectListDestroy - Destroy a list of objects
128e5c89e4eSSatish Balay 
129e5c89e4eSSatish Balay     Input Parameter:
1306bf464f9SBarry Smith .   ifl   - pointer to list
1311d0fab5eSBarry Smith 
132b235ab32SBarry Smith     Level: developer
133b235ab32SBarry Smith 
134db781477SPatrick Sanan .seealso: `PetscObjectListAdd()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()`, `PetscObjectListReverseFind()`, `PetscObjectListDuplicate()`
1351d0fab5eSBarry Smith @*/
1369371c9d4SSatish Balay PetscErrorCode PetscObjectListDestroy(PetscObjectList *ifl) {
1375f80ce2aSJacob Faibussowitsch   PetscObjectList tmp, fl;
138e5c89e4eSSatish Balay 
139e5c89e4eSSatish Balay   PetscFunctionBegin;
1405f80ce2aSJacob Faibussowitsch   PetscValidPointer(ifl, 1);
1415f80ce2aSJacob Faibussowitsch   fl = *ifl;
1429c666560SBarry Smith   while (fl) {
1439c666560SBarry Smith     tmp = fl->next;
1449566063dSJacob Faibussowitsch     if (!fl->skipdereference) PetscCall(PetscObjectDereference(fl->obj));
1459566063dSJacob Faibussowitsch     PetscCall(PetscFree(fl));
1469c666560SBarry Smith     fl = tmp;
147e5c89e4eSSatish Balay   }
1480298fd71SBarry Smith   *ifl = NULL;
149e5c89e4eSSatish Balay   PetscFunctionReturn(0);
150e5c89e4eSSatish Balay }
151e5c89e4eSSatish Balay 
1521d0fab5eSBarry Smith /*@C
153140e18c1SBarry Smith     PetscObjectListFind - givn a name, find the matching object
154e5c89e4eSSatish Balay 
155e5c89e4eSSatish Balay     Input Parameters:
156e5c89e4eSSatish Balay +   fl   - pointer to list
157e5c89e4eSSatish Balay -   name - name string
158e5c89e4eSSatish Balay 
159e5c89e4eSSatish Balay     Output Parameters:
1607243573dSPierre Jolivet .   obj - the PETSc object
161e5c89e4eSSatish Balay 
162b235ab32SBarry Smith     Level: developer
163b235ab32SBarry Smith 
164e5c89e4eSSatish Balay     Notes:
165*811af0c4SBarry Smith     The name must have been registered with the `PetscObjectListAdd()` before calling this routine.
1663c0c59f3SBarry Smith 
1673c0c59f3SBarry Smith     The reference count of the object is not increased
168e5c89e4eSSatish Balay 
169db781477SPatrick Sanan .seealso: `PetscObjectListDestroy()`, `PetscObjectListAdd()`, `PetscObjectListDuplicate()`, `PetscObjectListReverseFind()`, `PetscObjectListDuplicate()`
1701d0fab5eSBarry Smith @*/
1719371c9d4SSatish Balay PetscErrorCode PetscObjectListFind(PetscObjectList fl, const char name[], PetscObject *obj) {
172e5c89e4eSSatish Balay   PetscFunctionBegin;
1735f80ce2aSJacob Faibussowitsch   PetscValidPointer(obj, 3);
17402c9f0b5SLisandro Dalcin   *obj = NULL;
175e5c89e4eSSatish Balay   while (fl) {
1765f80ce2aSJacob Faibussowitsch     PetscBool match;
1779566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, fl->name, &match));
178e5c89e4eSSatish Balay     if (match) {
179e5c89e4eSSatish Balay       *obj = fl->obj;
180e5c89e4eSSatish Balay       break;
181e5c89e4eSSatish Balay     }
182e5c89e4eSSatish Balay     fl = fl->next;
183e5c89e4eSSatish Balay   }
184e5c89e4eSSatish Balay   PetscFunctionReturn(0);
185e5c89e4eSSatish Balay }
186e5c89e4eSSatish Balay 
1871d0fab5eSBarry Smith /*@C
188140e18c1SBarry Smith     PetscObjectListReverseFind - given a object, find the matching name if it exists
189e5c89e4eSSatish Balay 
190e5c89e4eSSatish Balay     Input Parameters:
191e5c89e4eSSatish Balay +   fl   - pointer to list
1927243573dSPierre Jolivet -   obj - the PETSc object
193e5c89e4eSSatish Balay 
194e5c89e4eSSatish Balay     Output Parameters:
195bfec8eecSBarry Smith +  name - name string
1965e8f358bSStefano Zampini -  skipdereference - if the object is in list but does not have the increased reference count for a circular dependency
197e5c89e4eSSatish Balay 
198b235ab32SBarry Smith     Level: developer
199b235ab32SBarry Smith 
200e5c89e4eSSatish Balay     Notes:
201*811af0c4SBarry Smith     The name must have been registered with the `PetscObjectListAdd()` before calling this routine.
2023c0c59f3SBarry Smith 
2033c0c59f3SBarry Smith     The reference count of the object is not increased
204e5c89e4eSSatish Balay 
205db781477SPatrick Sanan .seealso: `PetscObjectListDestroy()`, `PetscObjectListAdd()`, `PetscObjectListDuplicate()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()`
2061d0fab5eSBarry Smith @*/
2079371c9d4SSatish Balay PetscErrorCode PetscObjectListReverseFind(PetscObjectList fl, PetscObject obj, char **name, PetscBool *skipdereference) {
208e5c89e4eSSatish Balay   PetscFunctionBegin;
2095f80ce2aSJacob Faibussowitsch   PetscValidPointer(name, 3);
2105f80ce2aSJacob Faibussowitsch   if (skipdereference) PetscValidBoolPointer(skipdereference, 4);
21102c9f0b5SLisandro Dalcin   *name = NULL;
212e5c89e4eSSatish Balay   while (fl) {
213e5c89e4eSSatish Balay     if (fl->obj == obj) {
214e5c89e4eSSatish Balay       *name = fl->name;
215bfec8eecSBarry Smith       if (skipdereference) *skipdereference = fl->skipdereference;
216e5c89e4eSSatish Balay       break;
217e5c89e4eSSatish Balay     }
218e5c89e4eSSatish Balay     fl = fl->next;
219e5c89e4eSSatish Balay   }
220e5c89e4eSSatish Balay   PetscFunctionReturn(0);
221e5c89e4eSSatish Balay }
222e5c89e4eSSatish Balay 
2231d0fab5eSBarry Smith /*@C
2245e8f358bSStefano Zampini     PetscObjectListDuplicate - Creates a new list from a given object list.
225e5c89e4eSSatish Balay 
226e5c89e4eSSatish Balay     Input Parameters:
227e5c89e4eSSatish Balay .   fl   - pointer to list
228e5c89e4eSSatish Balay 
229e5c89e4eSSatish Balay     Output Parameters:
230e5c89e4eSSatish Balay .   nl - the new list (should point to 0 to start, otherwise appends)
231e5c89e4eSSatish Balay 
232b235ab32SBarry Smith     Level: developer
233b235ab32SBarry Smith 
234db781477SPatrick Sanan .seealso: `PetscObjectListDestroy()`, `PetscObjectListAdd()`, `PetscObjectListReverseFind()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()`
2351d0fab5eSBarry Smith @*/
2369371c9d4SSatish Balay PetscErrorCode PetscObjectListDuplicate(PetscObjectList fl, PetscObjectList *nl) {
237e5c89e4eSSatish Balay   PetscFunctionBegin;
2385f80ce2aSJacob Faibussowitsch   PetscValidPointer(nl, 2);
239e5c89e4eSSatish Balay   while (fl) {
2409566063dSJacob Faibussowitsch     PetscCall(PetscObjectListAdd(nl, fl->name, fl->obj));
241e5c89e4eSSatish Balay     fl = fl->next;
242e5c89e4eSSatish Balay   }
243e5c89e4eSSatish Balay   PetscFunctionReturn(0);
244e5c89e4eSSatish Balay }
245