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