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