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 16140e18c1SBarry 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: 2595452b02SPatrick Sanan 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 296ba4bc90SBarry Smith Developer Note: this is to handle some cases that otherwise would result in having circular references so reference counts never got to zero 306ba4bc90SBarry Smith 31db781477SPatrick Sanan .seealso: `PetscObjectListDestroy()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()`, `PetscObjectListReverseFind()`, `PetscObjectListDuplicate()`, `PetscObjectListAdd()` 326ba4bc90SBarry Smith 336ba4bc90SBarry Smith @*/ 34*9371c9d4SSatish 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 55140e18c1SBarry 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 67140e18c1SBarry Smith Use PetscObjectListFind() or PetscObjectListReverseFind() to get the object back 681d0fab5eSBarry Smith 69db781477SPatrick Sanan .seealso: `PetscObjectListDestroy()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()`, `PetscObjectListReverseFind()`, `PetscObjectListDuplicate()` 701d0fab5eSBarry Smith 711d0fab5eSBarry Smith @*/ 72*9371c9d4SSatish Balay PetscErrorCode PetscObjectListAdd(PetscObjectList *fl, const char name[], PetscObject obj) { 73140e18c1SBarry Smith PetscObjectList olist, nlist, prev; 74ace3abfcSBarry Smith PetscBool match; 75e5c89e4eSSatish Balay 76e5c89e4eSSatish Balay PetscFunctionBegin; 775f80ce2aSJacob Faibussowitsch PetscValidPointer(fl, 1); 78e5c89e4eSSatish Balay if (!obj) { /* this means remove from list if it is there */ 79*9371c9d4SSatish Balay nlist = *fl; 80*9371c9d4SSatish Balay prev = NULL; 81e5c89e4eSSatish Balay while (nlist) { 829566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, nlist->name, &match)); 83e5c89e4eSSatish Balay if (match) { /* found it already in the list */ 844a0791bcSMatthew G. Knepley /* Remove it first to prevent circular derefs */ 85e5c89e4eSSatish Balay if (prev) prev->next = nlist->next; 86a297a907SKarl Rupp else if (nlist->next) *fl = nlist->next; 8702c9f0b5SLisandro Dalcin else *fl = NULL; 889566063dSJacob Faibussowitsch if (!nlist->skipdereference) PetscCall(PetscObjectDereference(nlist->obj)); 899566063dSJacob Faibussowitsch PetscCall(PetscFree(nlist)); 90e5c89e4eSSatish Balay PetscFunctionReturn(0); 91e5c89e4eSSatish Balay } 92e5c89e4eSSatish Balay prev = nlist; 93e5c89e4eSSatish Balay nlist = nlist->next; 94e5c89e4eSSatish Balay } 95e5c89e4eSSatish Balay PetscFunctionReturn(0); /* did not find it to remove */ 96e5c89e4eSSatish Balay } 97e5c89e4eSSatish Balay /* look for it already in list */ 98e5c89e4eSSatish Balay nlist = *fl; 99e5c89e4eSSatish Balay while (nlist) { 1009566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, nlist->name, &match)); 101e5c89e4eSSatish Balay if (match) { /* found it in the list */ 1029566063dSJacob Faibussowitsch PetscCall(PetscObjectReference(obj)); 1039566063dSJacob Faibussowitsch if (!nlist->skipdereference) PetscCall(PetscObjectDereference(nlist->obj)); 10400ac8be1SBarry Smith nlist->skipdereference = PETSC_FALSE; 105e5c89e4eSSatish Balay nlist->obj = obj; 106e5c89e4eSSatish Balay PetscFunctionReturn(0); 107e5c89e4eSSatish Balay } 108e5c89e4eSSatish Balay nlist = nlist->next; 109e5c89e4eSSatish Balay } 110e5c89e4eSSatish Balay 111e5c89e4eSSatish Balay /* add it to list, because it was not already there */ 1129566063dSJacob Faibussowitsch PetscCall(PetscNew(&olist)); 11302c9f0b5SLisandro Dalcin olist->next = NULL; 114e5c89e4eSSatish Balay olist->obj = obj; 115a297a907SKarl Rupp 1169566063dSJacob Faibussowitsch PetscCall(PetscObjectReference(obj)); 1179566063dSJacob Faibussowitsch PetscCall(PetscStrcpy(olist->name, name)); 118e5c89e4eSSatish Balay 119a297a907SKarl Rupp if (!*fl) *fl = olist; 120*9371c9d4SSatish Balay else { /* go to end of list */ nlist = *fl; 1215f80ce2aSJacob Faibussowitsch while (nlist->next) nlist = nlist->next; 122e5c89e4eSSatish Balay nlist->next = olist; 123e5c89e4eSSatish Balay } 124e5c89e4eSSatish Balay PetscFunctionReturn(0); 125e5c89e4eSSatish Balay } 126e5c89e4eSSatish Balay 1271d0fab5eSBarry Smith /*@C 128140e18c1SBarry Smith PetscObjectListDestroy - Destroy a list of objects 129e5c89e4eSSatish Balay 130e5c89e4eSSatish Balay Input Parameter: 1316bf464f9SBarry Smith . ifl - pointer to list 1321d0fab5eSBarry Smith 133b235ab32SBarry Smith Level: developer 134b235ab32SBarry Smith 135db781477SPatrick Sanan .seealso: `PetscObjectListAdd()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()`, `PetscObjectListReverseFind()`, `PetscObjectListDuplicate()` 1361d0fab5eSBarry Smith 1371d0fab5eSBarry Smith @*/ 138*9371c9d4SSatish Balay PetscErrorCode PetscObjectListDestroy(PetscObjectList *ifl) { 1395f80ce2aSJacob Faibussowitsch PetscObjectList tmp, fl; 140e5c89e4eSSatish Balay 141e5c89e4eSSatish Balay PetscFunctionBegin; 1425f80ce2aSJacob Faibussowitsch PetscValidPointer(ifl, 1); 1435f80ce2aSJacob Faibussowitsch fl = *ifl; 1449c666560SBarry Smith while (fl) { 1459c666560SBarry Smith tmp = fl->next; 1469566063dSJacob Faibussowitsch if (!fl->skipdereference) PetscCall(PetscObjectDereference(fl->obj)); 1479566063dSJacob Faibussowitsch PetscCall(PetscFree(fl)); 1489c666560SBarry Smith fl = tmp; 149e5c89e4eSSatish Balay } 1500298fd71SBarry Smith *ifl = NULL; 151e5c89e4eSSatish Balay PetscFunctionReturn(0); 152e5c89e4eSSatish Balay } 153e5c89e4eSSatish Balay 1541d0fab5eSBarry Smith /*@C 155140e18c1SBarry Smith PetscObjectListFind - givn a name, find the matching object 156e5c89e4eSSatish Balay 157e5c89e4eSSatish Balay Input Parameters: 158e5c89e4eSSatish Balay + fl - pointer to list 159e5c89e4eSSatish Balay - name - name string 160e5c89e4eSSatish Balay 161e5c89e4eSSatish Balay Output Parameters: 1627243573dSPierre Jolivet . obj - the PETSc object 163e5c89e4eSSatish Balay 164b235ab32SBarry Smith Level: developer 165b235ab32SBarry Smith 166e5c89e4eSSatish Balay Notes: 167140e18c1SBarry Smith The name must have been registered with the PetscObjectListAdd() before calling this routine. 1683c0c59f3SBarry Smith 1693c0c59f3SBarry Smith The reference count of the object is not increased 170e5c89e4eSSatish Balay 171db781477SPatrick Sanan .seealso: `PetscObjectListDestroy()`, `PetscObjectListAdd()`, `PetscObjectListDuplicate()`, `PetscObjectListReverseFind()`, `PetscObjectListDuplicate()` 172e5c89e4eSSatish Balay 1731d0fab5eSBarry Smith @*/ 174*9371c9d4SSatish Balay PetscErrorCode PetscObjectListFind(PetscObjectList fl, const char name[], PetscObject *obj) { 175e5c89e4eSSatish Balay PetscFunctionBegin; 1765f80ce2aSJacob Faibussowitsch PetscValidPointer(obj, 3); 17702c9f0b5SLisandro Dalcin *obj = NULL; 178e5c89e4eSSatish Balay while (fl) { 1795f80ce2aSJacob Faibussowitsch PetscBool match; 1809566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, fl->name, &match)); 181e5c89e4eSSatish Balay if (match) { 182e5c89e4eSSatish Balay *obj = fl->obj; 183e5c89e4eSSatish Balay break; 184e5c89e4eSSatish Balay } 185e5c89e4eSSatish Balay fl = fl->next; 186e5c89e4eSSatish Balay } 187e5c89e4eSSatish Balay PetscFunctionReturn(0); 188e5c89e4eSSatish Balay } 189e5c89e4eSSatish Balay 1901d0fab5eSBarry Smith /*@C 191140e18c1SBarry Smith PetscObjectListReverseFind - given a object, find the matching name if it exists 192e5c89e4eSSatish Balay 193e5c89e4eSSatish Balay Input Parameters: 194e5c89e4eSSatish Balay + fl - pointer to list 1957243573dSPierre Jolivet - obj - the PETSc object 196e5c89e4eSSatish Balay 197e5c89e4eSSatish Balay Output Parameters: 198bfec8eecSBarry Smith + name - name string 1995e8f358bSStefano Zampini - skipdereference - if the object is in list but does not have the increased reference count for a circular dependency 200e5c89e4eSSatish Balay 201b235ab32SBarry Smith Level: developer 202b235ab32SBarry Smith 203e5c89e4eSSatish Balay Notes: 204140e18c1SBarry Smith The name must have been registered with the PetscObjectListAdd() before calling this routine. 2053c0c59f3SBarry Smith 2063c0c59f3SBarry Smith The reference count of the object is not increased 207e5c89e4eSSatish Balay 208db781477SPatrick Sanan .seealso: `PetscObjectListDestroy()`, `PetscObjectListAdd()`, `PetscObjectListDuplicate()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()` 209e5c89e4eSSatish Balay 2101d0fab5eSBarry Smith @*/ 211*9371c9d4SSatish Balay PetscErrorCode PetscObjectListReverseFind(PetscObjectList fl, PetscObject obj, char **name, PetscBool *skipdereference) { 212e5c89e4eSSatish Balay PetscFunctionBegin; 2135f80ce2aSJacob Faibussowitsch PetscValidPointer(name, 3); 2145f80ce2aSJacob Faibussowitsch if (skipdereference) PetscValidBoolPointer(skipdereference, 4); 21502c9f0b5SLisandro Dalcin *name = NULL; 216e5c89e4eSSatish Balay while (fl) { 217e5c89e4eSSatish Balay if (fl->obj == obj) { 218e5c89e4eSSatish Balay *name = fl->name; 219bfec8eecSBarry Smith if (skipdereference) *skipdereference = fl->skipdereference; 220e5c89e4eSSatish Balay break; 221e5c89e4eSSatish Balay } 222e5c89e4eSSatish Balay fl = fl->next; 223e5c89e4eSSatish Balay } 224e5c89e4eSSatish Balay PetscFunctionReturn(0); 225e5c89e4eSSatish Balay } 226e5c89e4eSSatish Balay 2271d0fab5eSBarry Smith /*@C 2285e8f358bSStefano Zampini PetscObjectListDuplicate - Creates a new list from a given object list. 229e5c89e4eSSatish Balay 230e5c89e4eSSatish Balay Input Parameters: 231e5c89e4eSSatish Balay . fl - pointer to list 232e5c89e4eSSatish Balay 233e5c89e4eSSatish Balay Output Parameters: 234e5c89e4eSSatish Balay . nl - the new list (should point to 0 to start, otherwise appends) 235e5c89e4eSSatish Balay 236b235ab32SBarry Smith Level: developer 237b235ab32SBarry Smith 238db781477SPatrick Sanan .seealso: `PetscObjectListDestroy()`, `PetscObjectListAdd()`, `PetscObjectListReverseFind()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()` 239e5c89e4eSSatish Balay 2401d0fab5eSBarry Smith @*/ 241*9371c9d4SSatish Balay PetscErrorCode PetscObjectListDuplicate(PetscObjectList fl, PetscObjectList *nl) { 242e5c89e4eSSatish Balay PetscFunctionBegin; 2435f80ce2aSJacob Faibussowitsch PetscValidPointer(nl, 2); 244e5c89e4eSSatish Balay while (fl) { 2459566063dSJacob Faibussowitsch PetscCall(PetscObjectListAdd(nl, fl->name, fl->obj)); 246e5c89e4eSSatish Balay fl = fl->next; 247e5c89e4eSSatish Balay } 248e5c89e4eSSatish Balay PetscFunctionReturn(0); 249e5c89e4eSSatish Balay } 250