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 16811af0c4SBarry 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: 25811af0c4SBarry 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*aec76313SJacob Faibussowitsch Developer Notes: 30811af0c4SBarry Smith This is to handle some cases that otherwise would result in having circular references so reference counts never got to zero 316ba4bc90SBarry Smith 32*aec76313SJacob Faibussowitsch .seealso: `PetscObjectListDestroy()`,`PetscObjectListFind()`,`PetscObjectListDuplicate()`,`PetscObjectListReverseFind()`, 3321532e8aSBarry Smith `PetscObject`, `PetscObjectListAdd()` 346ba4bc90SBarry Smith @*/ 35d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectListRemoveReference(PetscObjectList *fl, const char name[]) 36d71ae5a4SJacob Faibussowitsch { 37140e18c1SBarry Smith PetscObjectList nlist; 386ba4bc90SBarry Smith PetscBool match; 396ba4bc90SBarry Smith 406ba4bc90SBarry Smith PetscFunctionBegin; 415f80ce2aSJacob Faibussowitsch PetscValidPointer(fl, 1); 425f80ce2aSJacob Faibussowitsch PetscValidCharPointer(name, 2); 4387130e5eSHong Zhang nlist = *fl; 446ba4bc90SBarry Smith while (nlist) { 459566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, nlist->name, &match)); 4600ac8be1SBarry Smith if (match) { /* found it in the list */ 479566063dSJacob Faibussowitsch if (!nlist->skipdereference) PetscCall(PetscObjectDereference(nlist->obj)); 486ba4bc90SBarry Smith nlist->skipdereference = PETSC_TRUE; 493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 506ba4bc90SBarry Smith } 516ba4bc90SBarry Smith nlist = nlist->next; 526ba4bc90SBarry Smith } 533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 546ba4bc90SBarry Smith } 556ba4bc90SBarry Smith 561d0fab5eSBarry Smith /*@C 57811af0c4SBarry Smith PetscObjectListAdd - Adds a new object to an `PetscObjectList` 58e5c89e4eSSatish Balay 591d0fab5eSBarry Smith Input Parameters: 601d0fab5eSBarry Smith + fl - the object list 611d0fab5eSBarry Smith . name - the name to use for the object 621d0fab5eSBarry Smith - obj - the object to attach 63e5c89e4eSSatish Balay 64b235ab32SBarry Smith Level: developer 65b235ab32SBarry Smith 6695452b02SPatrick Sanan Notes: 6721532e8aSBarry Smith Replaces item if it is already in list. Removes item if you pass in a `NULL` object. 681d0fab5eSBarry Smith 69811af0c4SBarry Smith Use `PetscObjectListFind()` or `PetscObjectListReverseFind()` to get the object back 701d0fab5eSBarry Smith 71*aec76313SJacob Faibussowitsch .seealso: `PetscObjectListDestroy()`,`PetscObjectListFind()`,`PetscObjectListDuplicate()`,`PetscObjectListReverseFind()`, `PetscObject`, `PetscObjectList` 721d0fab5eSBarry Smith @*/ 73d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectListAdd(PetscObjectList *fl, const char name[], PetscObject obj) 74d71ae5a4SJacob Faibussowitsch { 75140e18c1SBarry Smith PetscObjectList olist, nlist, prev; 76ace3abfcSBarry Smith PetscBool match; 77e5c89e4eSSatish Balay 78e5c89e4eSSatish Balay PetscFunctionBegin; 795f80ce2aSJacob Faibussowitsch PetscValidPointer(fl, 1); 80e5c89e4eSSatish Balay if (!obj) { /* this means remove from list if it is there */ 819371c9d4SSatish Balay nlist = *fl; 829371c9d4SSatish Balay prev = NULL; 83e5c89e4eSSatish Balay while (nlist) { 849566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, nlist->name, &match)); 85e5c89e4eSSatish Balay if (match) { /* found it already in the list */ 864a0791bcSMatthew G. Knepley /* Remove it first to prevent circular derefs */ 87e5c89e4eSSatish Balay if (prev) prev->next = nlist->next; 88a297a907SKarl Rupp else if (nlist->next) *fl = nlist->next; 8902c9f0b5SLisandro Dalcin else *fl = NULL; 909566063dSJacob Faibussowitsch if (!nlist->skipdereference) PetscCall(PetscObjectDereference(nlist->obj)); 919566063dSJacob Faibussowitsch PetscCall(PetscFree(nlist)); 923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 93e5c89e4eSSatish Balay } 94e5c89e4eSSatish Balay prev = nlist; 95e5c89e4eSSatish Balay nlist = nlist->next; 96e5c89e4eSSatish Balay } 973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); /* did not find it to remove */ 98e5c89e4eSSatish Balay } 99e5c89e4eSSatish Balay /* look for it already in list */ 100e5c89e4eSSatish Balay nlist = *fl; 101e5c89e4eSSatish Balay while (nlist) { 1029566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, nlist->name, &match)); 103e5c89e4eSSatish Balay if (match) { /* found it in the list */ 1049566063dSJacob Faibussowitsch PetscCall(PetscObjectReference(obj)); 1059566063dSJacob Faibussowitsch if (!nlist->skipdereference) PetscCall(PetscObjectDereference(nlist->obj)); 10600ac8be1SBarry Smith nlist->skipdereference = PETSC_FALSE; 107e5c89e4eSSatish Balay nlist->obj = obj; 1083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 109e5c89e4eSSatish Balay } 110e5c89e4eSSatish Balay nlist = nlist->next; 111e5c89e4eSSatish Balay } 112e5c89e4eSSatish Balay 113e5c89e4eSSatish Balay /* add it to list, because it was not already there */ 1149566063dSJacob Faibussowitsch PetscCall(PetscNew(&olist)); 11502c9f0b5SLisandro Dalcin olist->next = NULL; 116e5c89e4eSSatish Balay olist->obj = obj; 117a297a907SKarl Rupp 1189566063dSJacob Faibussowitsch PetscCall(PetscObjectReference(obj)); 119c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(olist->name, name, sizeof(olist->name))); 120e5c89e4eSSatish Balay 121a297a907SKarl Rupp if (!*fl) *fl = olist; 1229371c9d4SSatish Balay else { /* go to end of list */ nlist = *fl; 1235f80ce2aSJacob Faibussowitsch while (nlist->next) nlist = nlist->next; 124e5c89e4eSSatish Balay nlist->next = olist; 125e5c89e4eSSatish Balay } 1263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 127e5c89e4eSSatish Balay } 128e5c89e4eSSatish Balay 1291d0fab5eSBarry Smith /*@C 130140e18c1SBarry Smith PetscObjectListDestroy - Destroy a list of objects 131e5c89e4eSSatish Balay 132e5c89e4eSSatish Balay Input Parameter: 1336bf464f9SBarry Smith . ifl - pointer to list 1341d0fab5eSBarry Smith 135b235ab32SBarry Smith Level: developer 136b235ab32SBarry Smith 13721532e8aSBarry Smith .seealso: `PetscObjectList`, `PetscObject`, `PetscObjectListAdd()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()`, 138*aec76313SJacob Faibussowitsch `PetscObjectListReverseFind()` 1391d0fab5eSBarry Smith @*/ 140d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectListDestroy(PetscObjectList *ifl) 141d71ae5a4SJacob Faibussowitsch { 1425f80ce2aSJacob Faibussowitsch PetscObjectList tmp, fl; 143e5c89e4eSSatish Balay 144e5c89e4eSSatish Balay PetscFunctionBegin; 1455f80ce2aSJacob Faibussowitsch PetscValidPointer(ifl, 1); 1465f80ce2aSJacob Faibussowitsch fl = *ifl; 1479c666560SBarry Smith while (fl) { 1489c666560SBarry Smith tmp = fl->next; 1499566063dSJacob Faibussowitsch if (!fl->skipdereference) PetscCall(PetscObjectDereference(fl->obj)); 1509566063dSJacob Faibussowitsch PetscCall(PetscFree(fl)); 1519c666560SBarry Smith fl = tmp; 152e5c89e4eSSatish Balay } 1530298fd71SBarry Smith *ifl = NULL; 1543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 155e5c89e4eSSatish Balay } 156e5c89e4eSSatish Balay 1571d0fab5eSBarry Smith /*@C 158fed58de9SStefano Zampini PetscObjectListFind - given a name, find the matching object in a list 159e5c89e4eSSatish Balay 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 174*aec76313SJacob 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; 1795f80ce2aSJacob Faibussowitsch PetscValidPointer(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 196e5c89e4eSSatish Balay Input Parameters: 197e5c89e4eSSatish Balay + fl - pointer to list 1987243573dSPierre Jolivet - obj - the PETSc object 199e5c89e4eSSatish Balay 200e5c89e4eSSatish Balay Output Parameters: 201bfec8eecSBarry Smith + name - name string 2025e8f358bSStefano Zampini - skipdereference - if the object is in list but does not have the increased reference count for a circular dependency 203e5c89e4eSSatish Balay 204b235ab32SBarry Smith Level: developer 205b235ab32SBarry Smith 206e5c89e4eSSatish Balay Notes: 207811af0c4SBarry Smith The name must have been registered with the `PetscObjectListAdd()` before calling this routine. 2083c0c59f3SBarry Smith 2093c0c59f3SBarry Smith The reference count of the object is not increased 210e5c89e4eSSatish Balay 211*aec76313SJacob Faibussowitsch .seealso: `PetscObjectListDestroy()`,`PetscObjectListAdd()`,`PetscObjectListDuplicate()`,`PetscObjectListFind()`, `PetscObjectList` 2121d0fab5eSBarry Smith @*/ 213d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectListReverseFind(PetscObjectList fl, PetscObject obj, char **name, PetscBool *skipdereference) 214d71ae5a4SJacob Faibussowitsch { 215e5c89e4eSSatish Balay PetscFunctionBegin; 2165f80ce2aSJacob Faibussowitsch PetscValidPointer(name, 3); 2175f80ce2aSJacob Faibussowitsch if (skipdereference) PetscValidBoolPointer(skipdereference, 4); 21802c9f0b5SLisandro Dalcin *name = NULL; 219e5c89e4eSSatish Balay while (fl) { 220e5c89e4eSSatish Balay if (fl->obj == obj) { 221e5c89e4eSSatish Balay *name = fl->name; 222bfec8eecSBarry Smith if (skipdereference) *skipdereference = fl->skipdereference; 223e5c89e4eSSatish Balay break; 224e5c89e4eSSatish Balay } 225e5c89e4eSSatish Balay fl = fl->next; 226e5c89e4eSSatish Balay } 2273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 228e5c89e4eSSatish Balay } 229e5c89e4eSSatish Balay 2301d0fab5eSBarry Smith /*@C 2315e8f358bSStefano Zampini PetscObjectListDuplicate - Creates a new list from a given object list. 232e5c89e4eSSatish Balay 2332fe279fdSBarry Smith Input Parameter: 234e5c89e4eSSatish Balay . fl - pointer to list 235e5c89e4eSSatish Balay 2362fe279fdSBarry Smith Output Parameter: 23721532e8aSBarry Smith . nl - the new list (should point to `NULL` to start, otherwise appends) 238e5c89e4eSSatish Balay 239b235ab32SBarry Smith Level: developer 240b235ab32SBarry Smith 241*aec76313SJacob Faibussowitsch .seealso: `PetscObjectListDestroy()`, `PetscObjectListAdd()`, `PetscObjectListReverseFind()`, 242*aec76313SJacob Faibussowitsch `PetscObjectListFind()`, `PetscObjectListDuplicate()`, `PetscObjectList` 2431d0fab5eSBarry Smith @*/ 244d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectListDuplicate(PetscObjectList fl, PetscObjectList *nl) 245d71ae5a4SJacob Faibussowitsch { 246e5c89e4eSSatish Balay PetscFunctionBegin; 2475f80ce2aSJacob Faibussowitsch PetscValidPointer(nl, 2); 248e5c89e4eSSatish Balay while (fl) { 2499566063dSJacob Faibussowitsch PetscCall(PetscObjectListAdd(nl, fl->name, fl->obj)); 250e5c89e4eSSatish Balay fl = fl->next; 251e5c89e4eSSatish Balay } 2523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 253e5c89e4eSSatish Balay } 254