xref: /petsc/src/sys/objects/olist.c (revision 6d8694c4fbab79f9439f1ad13c0386ba7ee1ca4b)
1e5c89e4eSSatish Balay /*
2e5c89e4eSSatish Balay          Provides a general mechanism to maintain a linked list of PETSc objects.
3e5c89e4eSSatish Balay      This is used to allow PETSc objects to carry a list of "composed" objects
4e5c89e4eSSatish Balay */
55f80ce2aSJacob Faibussowitsch #include <petsc/private/petscimpl.h>
6e5c89e4eSSatish Balay 
76ba4bc90SBarry Smith /*@C
8811af0c4SBarry Smith   PetscObjectListRemoveReference - Calls `PetscObjectDereference()` on an object in the list immediately but keeps a pointer to the object in the list.
96ba4bc90SBarry Smith 
10cc4c1da9SBarry Smith   No Fortran Support
11cc4c1da9SBarry Smith 
126ba4bc90SBarry Smith   Input Parameters:
136ba4bc90SBarry Smith + fl   - the object list
146ba4bc90SBarry Smith - name - the name to use for the object
156ba4bc90SBarry Smith 
166ba4bc90SBarry Smith   Level: developer
176ba4bc90SBarry Smith 
1895452b02SPatrick Sanan   Notes:
19811af0c4SBarry Smith   Use `PetscObjectListAdd`(`PetscObjectList`,const char name[],NULL) to truly remove the object from the list
206ba4bc90SBarry Smith 
216ba4bc90SBarry Smith   Use this routine ONLY if you know that the object referenced will remain in existence until the pointing object is destroyed
226ba4bc90SBarry Smith 
23aec76313SJacob Faibussowitsch   Developer Notes:
24811af0c4SBarry Smith   This is to handle some cases that otherwise would result in having circular references so reference counts never got to zero
256ba4bc90SBarry Smith 
26aec76313SJacob Faibussowitsch .seealso: `PetscObjectListDestroy()`,`PetscObjectListFind()`,`PetscObjectListDuplicate()`,`PetscObjectListReverseFind()`,
2721532e8aSBarry Smith `PetscObject`, `PetscObjectListAdd()`
286ba4bc90SBarry Smith @*/
PetscObjectListRemoveReference(PetscObjectList * fl,const char name[])29d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectListRemoveReference(PetscObjectList *fl, const char name[])
30d71ae5a4SJacob Faibussowitsch {
31140e18c1SBarry Smith   PetscObjectList nlist;
326ba4bc90SBarry Smith   PetscBool       match;
336ba4bc90SBarry Smith 
346ba4bc90SBarry Smith   PetscFunctionBegin;
354f572ea9SToby Isaac   PetscAssertPointer(fl, 1);
364f572ea9SToby Isaac   PetscAssertPointer(name, 2);
3787130e5eSHong Zhang   nlist = *fl;
386ba4bc90SBarry Smith   while (nlist) {
399566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, nlist->name, &match));
4000ac8be1SBarry Smith     if (match) { /* found it in the list */
419566063dSJacob Faibussowitsch       if (!nlist->skipdereference) PetscCall(PetscObjectDereference(nlist->obj));
426ba4bc90SBarry Smith       nlist->skipdereference = PETSC_TRUE;
433ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
446ba4bc90SBarry Smith     }
456ba4bc90SBarry Smith     nlist = nlist->next;
466ba4bc90SBarry Smith   }
473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
486ba4bc90SBarry Smith }
496ba4bc90SBarry Smith 
501d0fab5eSBarry Smith /*@C
51811af0c4SBarry Smith   PetscObjectListAdd - Adds a new object to an `PetscObjectList`
52e5c89e4eSSatish Balay 
53cc4c1da9SBarry Smith   No Fortran Support
54cc4c1da9SBarry Smith 
551d0fab5eSBarry Smith   Input Parameters:
561d0fab5eSBarry Smith + fl   - the object list
571d0fab5eSBarry Smith . name - the name to use for the object
581d0fab5eSBarry Smith - obj  - the object to attach
59e5c89e4eSSatish Balay 
60b235ab32SBarry Smith   Level: developer
61b235ab32SBarry Smith 
6295452b02SPatrick Sanan   Notes:
6321532e8aSBarry Smith   Replaces item if it is already in list. Removes item if you pass in a `NULL` object.
641d0fab5eSBarry Smith 
65811af0c4SBarry Smith   Use `PetscObjectListFind()` or `PetscObjectListReverseFind()` to get the object back
661d0fab5eSBarry Smith 
67aec76313SJacob Faibussowitsch .seealso: `PetscObjectListDestroy()`,`PetscObjectListFind()`,`PetscObjectListDuplicate()`,`PetscObjectListReverseFind()`, `PetscObject`, `PetscObjectList`
681d0fab5eSBarry Smith @*/
PetscObjectListAdd(PetscObjectList * fl,const char name[],PetscObject obj)69d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectListAdd(PetscObjectList *fl, const char name[], PetscObject obj)
70d71ae5a4SJacob Faibussowitsch {
71140e18c1SBarry Smith   PetscObjectList olist, nlist, prev;
72ace3abfcSBarry Smith   PetscBool       match;
73e5c89e4eSSatish Balay 
74e5c89e4eSSatish Balay   PetscFunctionBegin;
754f572ea9SToby Isaac   PetscAssertPointer(fl, 1);
76e5c89e4eSSatish Balay   if (!obj) { /* this means remove from list if it is there */
779371c9d4SSatish Balay     nlist = *fl;
789371c9d4SSatish Balay     prev  = NULL;
79e5c89e4eSSatish Balay     while (nlist) {
809566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, nlist->name, &match));
81e5c89e4eSSatish Balay       if (match) { /* found it already in the list */
824a0791bcSMatthew G. Knepley         /* Remove it first to prevent circular derefs */
83e5c89e4eSSatish Balay         if (prev) prev->next = nlist->next;
84a297a907SKarl Rupp         else if (nlist->next) *fl = nlist->next;
8502c9f0b5SLisandro Dalcin         else *fl = NULL;
869566063dSJacob Faibussowitsch         if (!nlist->skipdereference) PetscCall(PetscObjectDereference(nlist->obj));
879566063dSJacob Faibussowitsch         PetscCall(PetscFree(nlist));
883ba16761SJacob Faibussowitsch         PetscFunctionReturn(PETSC_SUCCESS);
89e5c89e4eSSatish Balay       }
90e5c89e4eSSatish Balay       prev  = nlist;
91e5c89e4eSSatish Balay       nlist = nlist->next;
92e5c89e4eSSatish Balay     }
933ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS); /* did not find it to remove */
94e5c89e4eSSatish Balay   }
95e5c89e4eSSatish Balay   /* look for it already in list */
96e5c89e4eSSatish Balay   nlist = *fl;
97e5c89e4eSSatish Balay   while (nlist) {
989566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, nlist->name, &match));
99e5c89e4eSSatish Balay     if (match) { /* found it in the list */
1009566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference(obj));
1019566063dSJacob Faibussowitsch       if (!nlist->skipdereference) PetscCall(PetscObjectDereference(nlist->obj));
10200ac8be1SBarry Smith       nlist->skipdereference = PETSC_FALSE;
103e5c89e4eSSatish Balay       nlist->obj             = obj;
1043ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
105e5c89e4eSSatish Balay     }
106e5c89e4eSSatish Balay     nlist = nlist->next;
107e5c89e4eSSatish Balay   }
108e5c89e4eSSatish Balay 
109e5c89e4eSSatish Balay   /* add it to list, because it was not already there */
1109566063dSJacob Faibussowitsch   PetscCall(PetscNew(&olist));
11102c9f0b5SLisandro Dalcin   olist->next = NULL;
112e5c89e4eSSatish Balay   olist->obj  = obj;
113a297a907SKarl Rupp 
1149566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference(obj));
115c6a7a370SJeremy L Thompson   PetscCall(PetscStrncpy(olist->name, name, sizeof(olist->name)));
116e5c89e4eSSatish Balay 
117a297a907SKarl Rupp   if (!*fl) *fl = olist;
1189371c9d4SSatish Balay   else { /* go to end of list */ nlist = *fl;
1195f80ce2aSJacob Faibussowitsch     while (nlist->next) nlist = nlist->next;
120e5c89e4eSSatish Balay     nlist->next = olist;
121e5c89e4eSSatish Balay   }
1223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
123e5c89e4eSSatish Balay }
124e5c89e4eSSatish Balay 
1251d0fab5eSBarry Smith /*@C
126140e18c1SBarry Smith   PetscObjectListDestroy - Destroy a list of objects
127e5c89e4eSSatish Balay 
128cc4c1da9SBarry Smith   No Fortran Support
129cc4c1da9SBarry Smith 
130e5c89e4eSSatish Balay   Input Parameter:
1316bf464f9SBarry Smith . ifl - pointer to list
1321d0fab5eSBarry Smith 
133b235ab32SBarry Smith   Level: developer
134b235ab32SBarry Smith 
13521532e8aSBarry Smith .seealso: `PetscObjectList`, `PetscObject`, `PetscObjectListAdd()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()`,
136aec76313SJacob Faibussowitsch           `PetscObjectListReverseFind()`
1371d0fab5eSBarry Smith @*/
PetscObjectListDestroy(PetscObjectList * ifl)138d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectListDestroy(PetscObjectList *ifl)
139d71ae5a4SJacob Faibussowitsch {
1405f80ce2aSJacob Faibussowitsch   PetscObjectList tmp, fl;
141e5c89e4eSSatish Balay 
142e5c89e4eSSatish Balay   PetscFunctionBegin;
1434f572ea9SToby Isaac   PetscAssertPointer(ifl, 1);
1445f80ce2aSJacob Faibussowitsch   fl = *ifl;
1459c666560SBarry Smith   while (fl) {
1469c666560SBarry Smith     tmp = fl->next;
1479566063dSJacob Faibussowitsch     if (!fl->skipdereference) PetscCall(PetscObjectDereference(fl->obj));
1489566063dSJacob Faibussowitsch     PetscCall(PetscFree(fl));
1499c666560SBarry Smith     fl = tmp;
150e5c89e4eSSatish Balay   }
1510298fd71SBarry Smith   *ifl = NULL;
1523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
153e5c89e4eSSatish Balay }
154e5c89e4eSSatish Balay 
1551d0fab5eSBarry Smith /*@C
156fed58de9SStefano Zampini   PetscObjectListFind - given a name, find the matching object in a list
157e5c89e4eSSatish Balay 
158cc4c1da9SBarry Smith   No Fortran Support
159cc4c1da9SBarry Smith 
160e5c89e4eSSatish Balay   Input Parameters:
161e5c89e4eSSatish Balay + fl   - pointer to list
162e5c89e4eSSatish Balay - name - name string
163e5c89e4eSSatish Balay 
1642fe279fdSBarry Smith   Output Parameter:
1657243573dSPierre Jolivet . obj - the PETSc object
166e5c89e4eSSatish Balay 
167b235ab32SBarry Smith   Level: developer
168b235ab32SBarry Smith 
169e5c89e4eSSatish Balay   Notes:
170811af0c4SBarry Smith   The name must have been registered with the `PetscObjectListAdd()` before calling this routine.
1713c0c59f3SBarry Smith 
1723c0c59f3SBarry Smith   The reference count of the object is not increased
173e5c89e4eSSatish Balay 
174aec76313SJacob Faibussowitsch .seealso: `PetscObjectListDestroy()`,`PetscObjectListAdd()`,`PetscObjectListDuplicate()`,`PetscObjectListReverseFind()`, `PetscObjectList`
1751d0fab5eSBarry Smith @*/
PetscObjectListFind(PetscObjectList fl,const char name[],PetscObject * obj)176d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectListFind(PetscObjectList fl, const char name[], PetscObject *obj)
177d71ae5a4SJacob Faibussowitsch {
178e5c89e4eSSatish Balay   PetscFunctionBegin;
1794f572ea9SToby Isaac   PetscAssertPointer(obj, 3);
18002c9f0b5SLisandro Dalcin   *obj = NULL;
181e5c89e4eSSatish Balay   while (fl) {
1825f80ce2aSJacob Faibussowitsch     PetscBool match;
1839566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, fl->name, &match));
184e5c89e4eSSatish Balay     if (match) {
185e5c89e4eSSatish Balay       *obj = fl->obj;
186e5c89e4eSSatish Balay       break;
187e5c89e4eSSatish Balay     }
188e5c89e4eSSatish Balay     fl = fl->next;
189e5c89e4eSSatish Balay   }
1903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
191e5c89e4eSSatish Balay }
192e5c89e4eSSatish Balay 
1931d0fab5eSBarry Smith /*@C
194140e18c1SBarry Smith   PetscObjectListReverseFind - given a object, find the matching name if it exists
195e5c89e4eSSatish Balay 
196cc4c1da9SBarry Smith   No Fortran Support
197cc4c1da9SBarry Smith 
198e5c89e4eSSatish Balay   Input Parameters:
199e5c89e4eSSatish Balay + fl  - pointer to list
2007243573dSPierre Jolivet - obj - the PETSc object
201e5c89e4eSSatish Balay 
202e5c89e4eSSatish Balay   Output Parameters:
203bfec8eecSBarry Smith + name            - name string
2045e8f358bSStefano Zampini - skipdereference - if the object is in list but does not have the increased reference count for a circular dependency
205e5c89e4eSSatish Balay 
206b235ab32SBarry Smith   Level: developer
207b235ab32SBarry Smith 
208e5c89e4eSSatish Balay   Notes:
209811af0c4SBarry Smith   The name must have been registered with the `PetscObjectListAdd()` before calling this routine.
2103c0c59f3SBarry Smith 
2113c0c59f3SBarry Smith   The reference count of the object is not increased
212e5c89e4eSSatish Balay 
213aec76313SJacob Faibussowitsch .seealso: `PetscObjectListDestroy()`,`PetscObjectListAdd()`,`PetscObjectListDuplicate()`,`PetscObjectListFind()`, `PetscObjectList`
2141d0fab5eSBarry Smith @*/
PetscObjectListReverseFind(PetscObjectList fl,PetscObject obj,const char * name[],PetscBool * skipdereference)215*ce78bad3SBarry Smith PetscErrorCode PetscObjectListReverseFind(PetscObjectList fl, PetscObject obj, const char *name[], PetscBool *skipdereference)
216d71ae5a4SJacob Faibussowitsch {
217e5c89e4eSSatish Balay   PetscFunctionBegin;
2184f572ea9SToby Isaac   PetscAssertPointer(name, 3);
2194f572ea9SToby Isaac   if (skipdereference) PetscAssertPointer(skipdereference, 4);
22002c9f0b5SLisandro Dalcin   *name = NULL;
221e5c89e4eSSatish Balay   while (fl) {
222e5c89e4eSSatish Balay     if (fl->obj == obj) {
223e5c89e4eSSatish Balay       *name = fl->name;
224bfec8eecSBarry Smith       if (skipdereference) *skipdereference = fl->skipdereference;
225e5c89e4eSSatish Balay       break;
226e5c89e4eSSatish Balay     }
227e5c89e4eSSatish Balay     fl = fl->next;
228e5c89e4eSSatish Balay   }
2293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
230e5c89e4eSSatish Balay }
231e5c89e4eSSatish Balay 
2321d0fab5eSBarry Smith /*@C
2335e8f358bSStefano Zampini   PetscObjectListDuplicate - Creates a new list from a given object list.
234e5c89e4eSSatish Balay 
235cc4c1da9SBarry Smith   No Fortran Support
236cc4c1da9SBarry Smith 
2372fe279fdSBarry Smith   Input Parameter:
238e5c89e4eSSatish Balay . fl - pointer to list
239e5c89e4eSSatish Balay 
2402fe279fdSBarry Smith   Output Parameter:
24121532e8aSBarry Smith . nl - the new list (should point to `NULL` to start, otherwise appends)
242e5c89e4eSSatish Balay 
243b235ab32SBarry Smith   Level: developer
244b235ab32SBarry Smith 
245aec76313SJacob Faibussowitsch .seealso: `PetscObjectListDestroy()`, `PetscObjectListAdd()`, `PetscObjectListReverseFind()`,
24642747ad1SJacob Faibussowitsch `PetscObjectListFind()`, `PetscObjectList`
2471d0fab5eSBarry Smith @*/
PetscObjectListDuplicate(PetscObjectList fl,PetscObjectList * nl)248d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectListDuplicate(PetscObjectList fl, PetscObjectList *nl)
249d71ae5a4SJacob Faibussowitsch {
250e5c89e4eSSatish Balay   PetscFunctionBegin;
2514f572ea9SToby Isaac   PetscAssertPointer(nl, 2);
252e5c89e4eSSatish Balay   while (fl) {
2539566063dSJacob Faibussowitsch     PetscCall(PetscObjectListAdd(nl, fl->name, fl->obj));
254e5c89e4eSSatish Balay     fl = fl->next;
255e5c89e4eSSatish Balay   }
2563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
257e5c89e4eSSatish Balay }
258