xref: /petsc/src/sys/objects/olist.c (revision 42747ad1c0f89c178fc384aacf6345db4954f4b1)
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 
86ba4bc90SBarry Smith /*@C
9811af0c4SBarry Smith   PetscObjectListRemoveReference - Calls `PetscObjectDereference()` on an object in the list immediately but keeps a pointer to the object in the list.
106ba4bc90SBarry Smith 
116ba4bc90SBarry Smith   Input Parameters:
126ba4bc90SBarry Smith + fl   - the object list
136ba4bc90SBarry Smith - name - the name to use for the object
146ba4bc90SBarry Smith 
156ba4bc90SBarry Smith   Level: developer
166ba4bc90SBarry Smith 
1795452b02SPatrick Sanan   Notes:
18811af0c4SBarry Smith   Use `PetscObjectListAdd`(`PetscObjectList`,const char name[],NULL) to truly remove the object from the list
196ba4bc90SBarry Smith 
206ba4bc90SBarry Smith   Use this routine ONLY if you know that the object referenced will remain in existence until the pointing object is destroyed
216ba4bc90SBarry Smith 
22aec76313SJacob Faibussowitsch   Developer Notes:
23811af0c4SBarry Smith   This is to handle some cases that otherwise would result in having circular references so reference counts never got to zero
246ba4bc90SBarry Smith 
25aec76313SJacob Faibussowitsch .seealso: `PetscObjectListDestroy()`,`PetscObjectListFind()`,`PetscObjectListDuplicate()`,`PetscObjectListReverseFind()`,
2621532e8aSBarry Smith `PetscObject`, `PetscObjectListAdd()`
276ba4bc90SBarry Smith @*/
28d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectListRemoveReference(PetscObjectList *fl, const char name[])
29d71ae5a4SJacob Faibussowitsch {
30140e18c1SBarry Smith   PetscObjectList nlist;
316ba4bc90SBarry Smith   PetscBool       match;
326ba4bc90SBarry Smith 
336ba4bc90SBarry Smith   PetscFunctionBegin;
344f572ea9SToby Isaac   PetscAssertPointer(fl, 1);
354f572ea9SToby Isaac   PetscAssertPointer(name, 2);
3687130e5eSHong Zhang   nlist = *fl;
376ba4bc90SBarry Smith   while (nlist) {
389566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, nlist->name, &match));
3900ac8be1SBarry Smith     if (match) { /* found it in the list */
409566063dSJacob Faibussowitsch       if (!nlist->skipdereference) PetscCall(PetscObjectDereference(nlist->obj));
416ba4bc90SBarry Smith       nlist->skipdereference = PETSC_TRUE;
423ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
436ba4bc90SBarry Smith     }
446ba4bc90SBarry Smith     nlist = nlist->next;
456ba4bc90SBarry Smith   }
463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
476ba4bc90SBarry Smith }
486ba4bc90SBarry Smith 
491d0fab5eSBarry Smith /*@C
50811af0c4SBarry Smith   PetscObjectListAdd - Adds a new object to an `PetscObjectList`
51e5c89e4eSSatish Balay 
521d0fab5eSBarry Smith   Input Parameters:
531d0fab5eSBarry Smith + fl   - the object list
541d0fab5eSBarry Smith . name - the name to use for the object
551d0fab5eSBarry Smith - obj  - the object to attach
56e5c89e4eSSatish Balay 
57b235ab32SBarry Smith   Level: developer
58b235ab32SBarry Smith 
5995452b02SPatrick Sanan   Notes:
6021532e8aSBarry Smith   Replaces item if it is already in list. Removes item if you pass in a `NULL` object.
611d0fab5eSBarry Smith 
62811af0c4SBarry Smith   Use `PetscObjectListFind()` or `PetscObjectListReverseFind()` to get the object back
631d0fab5eSBarry Smith 
64aec76313SJacob Faibussowitsch .seealso: `PetscObjectListDestroy()`,`PetscObjectListFind()`,`PetscObjectListDuplicate()`,`PetscObjectListReverseFind()`, `PetscObject`, `PetscObjectList`
651d0fab5eSBarry Smith @*/
66d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectListAdd(PetscObjectList *fl, const char name[], PetscObject obj)
67d71ae5a4SJacob Faibussowitsch {
68140e18c1SBarry Smith   PetscObjectList olist, nlist, prev;
69ace3abfcSBarry Smith   PetscBool       match;
70e5c89e4eSSatish Balay 
71e5c89e4eSSatish Balay   PetscFunctionBegin;
724f572ea9SToby Isaac   PetscAssertPointer(fl, 1);
73e5c89e4eSSatish Balay   if (!obj) { /* this means remove from list if it is there */
749371c9d4SSatish Balay     nlist = *fl;
759371c9d4SSatish Balay     prev  = NULL;
76e5c89e4eSSatish Balay     while (nlist) {
779566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, nlist->name, &match));
78e5c89e4eSSatish Balay       if (match) { /* found it already in the list */
794a0791bcSMatthew G. Knepley         /* Remove it first to prevent circular derefs */
80e5c89e4eSSatish Balay         if (prev) prev->next = nlist->next;
81a297a907SKarl Rupp         else if (nlist->next) *fl = nlist->next;
8202c9f0b5SLisandro Dalcin         else *fl = NULL;
839566063dSJacob Faibussowitsch         if (!nlist->skipdereference) PetscCall(PetscObjectDereference(nlist->obj));
849566063dSJacob Faibussowitsch         PetscCall(PetscFree(nlist));
853ba16761SJacob Faibussowitsch         PetscFunctionReturn(PETSC_SUCCESS);
86e5c89e4eSSatish Balay       }
87e5c89e4eSSatish Balay       prev  = nlist;
88e5c89e4eSSatish Balay       nlist = nlist->next;
89e5c89e4eSSatish Balay     }
903ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS); /* did not find it to remove */
91e5c89e4eSSatish Balay   }
92e5c89e4eSSatish Balay   /* look for it already in list */
93e5c89e4eSSatish Balay   nlist = *fl;
94e5c89e4eSSatish Balay   while (nlist) {
959566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, nlist->name, &match));
96e5c89e4eSSatish Balay     if (match) { /* found it in the list */
979566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference(obj));
989566063dSJacob Faibussowitsch       if (!nlist->skipdereference) PetscCall(PetscObjectDereference(nlist->obj));
9900ac8be1SBarry Smith       nlist->skipdereference = PETSC_FALSE;
100e5c89e4eSSatish Balay       nlist->obj             = obj;
1013ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
102e5c89e4eSSatish Balay     }
103e5c89e4eSSatish Balay     nlist = nlist->next;
104e5c89e4eSSatish Balay   }
105e5c89e4eSSatish Balay 
106e5c89e4eSSatish Balay   /* add it to list, because it was not already there */
1079566063dSJacob Faibussowitsch   PetscCall(PetscNew(&olist));
10802c9f0b5SLisandro Dalcin   olist->next = NULL;
109e5c89e4eSSatish Balay   olist->obj  = obj;
110a297a907SKarl Rupp 
1119566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference(obj));
112c6a7a370SJeremy L Thompson   PetscCall(PetscStrncpy(olist->name, name, sizeof(olist->name)));
113e5c89e4eSSatish Balay 
114a297a907SKarl Rupp   if (!*fl) *fl = olist;
1159371c9d4SSatish Balay   else { /* go to end of list */ nlist = *fl;
1165f80ce2aSJacob Faibussowitsch     while (nlist->next) nlist = nlist->next;
117e5c89e4eSSatish Balay     nlist->next = olist;
118e5c89e4eSSatish Balay   }
1193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
120e5c89e4eSSatish Balay }
121e5c89e4eSSatish Balay 
1221d0fab5eSBarry Smith /*@C
123140e18c1SBarry Smith   PetscObjectListDestroy - Destroy a list of objects
124e5c89e4eSSatish Balay 
125e5c89e4eSSatish Balay   Input Parameter:
1266bf464f9SBarry Smith . ifl - pointer to list
1271d0fab5eSBarry Smith 
128b235ab32SBarry Smith   Level: developer
129b235ab32SBarry Smith 
13021532e8aSBarry Smith .seealso: `PetscObjectList`, `PetscObject`, `PetscObjectListAdd()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()`,
131aec76313SJacob Faibussowitsch           `PetscObjectListReverseFind()`
1321d0fab5eSBarry Smith @*/
133d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectListDestroy(PetscObjectList *ifl)
134d71ae5a4SJacob Faibussowitsch {
1355f80ce2aSJacob Faibussowitsch   PetscObjectList tmp, fl;
136e5c89e4eSSatish Balay 
137e5c89e4eSSatish Balay   PetscFunctionBegin;
1384f572ea9SToby Isaac   PetscAssertPointer(ifl, 1);
1395f80ce2aSJacob Faibussowitsch   fl = *ifl;
1409c666560SBarry Smith   while (fl) {
1419c666560SBarry Smith     tmp = fl->next;
1429566063dSJacob Faibussowitsch     if (!fl->skipdereference) PetscCall(PetscObjectDereference(fl->obj));
1439566063dSJacob Faibussowitsch     PetscCall(PetscFree(fl));
1449c666560SBarry Smith     fl = tmp;
145e5c89e4eSSatish Balay   }
1460298fd71SBarry Smith   *ifl = NULL;
1473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
148e5c89e4eSSatish Balay }
149e5c89e4eSSatish Balay 
1501d0fab5eSBarry Smith /*@C
151fed58de9SStefano Zampini   PetscObjectListFind - given a name, find the matching object in a list
152e5c89e4eSSatish Balay 
153e5c89e4eSSatish Balay   Input Parameters:
154e5c89e4eSSatish Balay + fl   - pointer to list
155e5c89e4eSSatish Balay - name - name string
156e5c89e4eSSatish Balay 
1572fe279fdSBarry Smith   Output Parameter:
1587243573dSPierre Jolivet . obj - the PETSc object
159e5c89e4eSSatish Balay 
160b235ab32SBarry Smith   Level: developer
161b235ab32SBarry Smith 
162e5c89e4eSSatish Balay   Notes:
163811af0c4SBarry Smith   The name must have been registered with the `PetscObjectListAdd()` before calling this routine.
1643c0c59f3SBarry Smith 
1653c0c59f3SBarry Smith   The reference count of the object is not increased
166e5c89e4eSSatish Balay 
167aec76313SJacob Faibussowitsch .seealso: `PetscObjectListDestroy()`,`PetscObjectListAdd()`,`PetscObjectListDuplicate()`,`PetscObjectListReverseFind()`, `PetscObjectList`
1681d0fab5eSBarry Smith @*/
169d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectListFind(PetscObjectList fl, const char name[], PetscObject *obj)
170d71ae5a4SJacob Faibussowitsch {
171e5c89e4eSSatish Balay   PetscFunctionBegin;
1724f572ea9SToby Isaac   PetscAssertPointer(obj, 3);
17302c9f0b5SLisandro Dalcin   *obj = NULL;
174e5c89e4eSSatish Balay   while (fl) {
1755f80ce2aSJacob Faibussowitsch     PetscBool match;
1769566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, fl->name, &match));
177e5c89e4eSSatish Balay     if (match) {
178e5c89e4eSSatish Balay       *obj = fl->obj;
179e5c89e4eSSatish Balay       break;
180e5c89e4eSSatish Balay     }
181e5c89e4eSSatish Balay     fl = fl->next;
182e5c89e4eSSatish Balay   }
1833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
184e5c89e4eSSatish Balay }
185e5c89e4eSSatish Balay 
1861d0fab5eSBarry Smith /*@C
187140e18c1SBarry Smith   PetscObjectListReverseFind - given a object, find the matching name if it exists
188e5c89e4eSSatish Balay 
189e5c89e4eSSatish Balay   Input Parameters:
190e5c89e4eSSatish Balay + fl  - pointer to list
1917243573dSPierre Jolivet - obj - the PETSc object
192e5c89e4eSSatish Balay 
193e5c89e4eSSatish Balay   Output Parameters:
194bfec8eecSBarry Smith + name            - name string
1955e8f358bSStefano Zampini - skipdereference - if the object is in list but does not have the increased reference count for a circular dependency
196e5c89e4eSSatish Balay 
197b235ab32SBarry Smith   Level: developer
198b235ab32SBarry Smith 
199e5c89e4eSSatish Balay   Notes:
200811af0c4SBarry Smith   The name must have been registered with the `PetscObjectListAdd()` before calling this routine.
2013c0c59f3SBarry Smith 
2023c0c59f3SBarry Smith   The reference count of the object is not increased
203e5c89e4eSSatish Balay 
204aec76313SJacob Faibussowitsch .seealso: `PetscObjectListDestroy()`,`PetscObjectListAdd()`,`PetscObjectListDuplicate()`,`PetscObjectListFind()`, `PetscObjectList`
2051d0fab5eSBarry Smith @*/
206d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectListReverseFind(PetscObjectList fl, PetscObject obj, char **name, PetscBool *skipdereference)
207d71ae5a4SJacob Faibussowitsch {
208e5c89e4eSSatish Balay   PetscFunctionBegin;
2094f572ea9SToby Isaac   PetscAssertPointer(name, 3);
2104f572ea9SToby Isaac   if (skipdereference) PetscAssertPointer(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   }
2203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
221e5c89e4eSSatish Balay }
222e5c89e4eSSatish Balay 
2231d0fab5eSBarry Smith /*@C
2245e8f358bSStefano Zampini   PetscObjectListDuplicate - Creates a new list from a given object list.
225e5c89e4eSSatish Balay 
2262fe279fdSBarry Smith   Input Parameter:
227e5c89e4eSSatish Balay . fl - pointer to list
228e5c89e4eSSatish Balay 
2292fe279fdSBarry Smith   Output Parameter:
23021532e8aSBarry Smith . nl - the new list (should point to `NULL` to start, otherwise appends)
231e5c89e4eSSatish Balay 
232b235ab32SBarry Smith   Level: developer
233b235ab32SBarry Smith 
234aec76313SJacob Faibussowitsch .seealso: `PetscObjectListDestroy()`, `PetscObjectListAdd()`, `PetscObjectListReverseFind()`,
235*42747ad1SJacob Faibussowitsch `PetscObjectListFind()`, `PetscObjectList`
2361d0fab5eSBarry Smith @*/
237d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectListDuplicate(PetscObjectList fl, PetscObjectList *nl)
238d71ae5a4SJacob Faibussowitsch {
239e5c89e4eSSatish Balay   PetscFunctionBegin;
2404f572ea9SToby Isaac   PetscAssertPointer(nl, 2);
241e5c89e4eSSatish Balay   while (fl) {
2429566063dSJacob Faibussowitsch     PetscCall(PetscObjectListAdd(nl, fl->name, fl->obj));
243e5c89e4eSSatish Balay     fl = fl->next;
244e5c89e4eSSatish Balay   }
2453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
246e5c89e4eSSatish Balay }
247