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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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