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