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 29811af0c4SBarry Smith Developer Note: 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*21532e8aSBarry Smith .seealso: `PetscObjectListDestroy()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()`, `PetscObjectListReverseFind()`, `PetscObjectListDuplicate()`, 33*21532e8aSBarry 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: 67*21532e8aSBarry 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*21532e8aSBarry Smith .seealso: `PetscObjectListDestroy()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()`, `PetscObjectListReverseFind()`, `PetscObjectListDuplicate()`, 72*21532e8aSBarry Smith `PetscObject`, `PetscObjectList` 731d0fab5eSBarry Smith @*/ 74d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectListAdd(PetscObjectList *fl, const char name[], PetscObject obj) 75d71ae5a4SJacob Faibussowitsch { 76140e18c1SBarry Smith PetscObjectList olist, nlist, prev; 77ace3abfcSBarry Smith PetscBool match; 78e5c89e4eSSatish Balay 79e5c89e4eSSatish Balay PetscFunctionBegin; 805f80ce2aSJacob Faibussowitsch PetscValidPointer(fl, 1); 81e5c89e4eSSatish Balay if (!obj) { /* this means remove from list if it is there */ 829371c9d4SSatish Balay nlist = *fl; 839371c9d4SSatish Balay prev = NULL; 84e5c89e4eSSatish Balay while (nlist) { 859566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, nlist->name, &match)); 86e5c89e4eSSatish Balay if (match) { /* found it already in the list */ 874a0791bcSMatthew G. Knepley /* Remove it first to prevent circular derefs */ 88e5c89e4eSSatish Balay if (prev) prev->next = nlist->next; 89a297a907SKarl Rupp else if (nlist->next) *fl = nlist->next; 9002c9f0b5SLisandro Dalcin else *fl = NULL; 919566063dSJacob Faibussowitsch if (!nlist->skipdereference) PetscCall(PetscObjectDereference(nlist->obj)); 929566063dSJacob Faibussowitsch PetscCall(PetscFree(nlist)); 933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 94e5c89e4eSSatish Balay } 95e5c89e4eSSatish Balay prev = nlist; 96e5c89e4eSSatish Balay nlist = nlist->next; 97e5c89e4eSSatish Balay } 983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); /* did not find it to remove */ 99e5c89e4eSSatish Balay } 100e5c89e4eSSatish Balay /* look for it already in list */ 101e5c89e4eSSatish Balay nlist = *fl; 102e5c89e4eSSatish Balay while (nlist) { 1039566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, nlist->name, &match)); 104e5c89e4eSSatish Balay if (match) { /* found it in the list */ 1059566063dSJacob Faibussowitsch PetscCall(PetscObjectReference(obj)); 1069566063dSJacob Faibussowitsch if (!nlist->skipdereference) PetscCall(PetscObjectDereference(nlist->obj)); 10700ac8be1SBarry Smith nlist->skipdereference = PETSC_FALSE; 108e5c89e4eSSatish Balay nlist->obj = obj; 1093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 110e5c89e4eSSatish Balay } 111e5c89e4eSSatish Balay nlist = nlist->next; 112e5c89e4eSSatish Balay } 113e5c89e4eSSatish Balay 114e5c89e4eSSatish Balay /* add it to list, because it was not already there */ 1159566063dSJacob Faibussowitsch PetscCall(PetscNew(&olist)); 11602c9f0b5SLisandro Dalcin olist->next = NULL; 117e5c89e4eSSatish Balay olist->obj = obj; 118a297a907SKarl Rupp 1199566063dSJacob Faibussowitsch PetscCall(PetscObjectReference(obj)); 120c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(olist->name, name, sizeof(olist->name))); 121e5c89e4eSSatish Balay 122a297a907SKarl Rupp if (!*fl) *fl = olist; 1239371c9d4SSatish Balay else { /* go to end of list */ nlist = *fl; 1245f80ce2aSJacob Faibussowitsch while (nlist->next) nlist = nlist->next; 125e5c89e4eSSatish Balay nlist->next = olist; 126e5c89e4eSSatish Balay } 1273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 128e5c89e4eSSatish Balay } 129e5c89e4eSSatish Balay 1301d0fab5eSBarry Smith /*@C 131140e18c1SBarry Smith PetscObjectListDestroy - Destroy a list of objects 132e5c89e4eSSatish Balay 133e5c89e4eSSatish Balay Input Parameter: 1346bf464f9SBarry Smith . ifl - pointer to list 1351d0fab5eSBarry Smith 136b235ab32SBarry Smith Level: developer 137b235ab32SBarry Smith 138*21532e8aSBarry Smith .seealso: `PetscObjectList`, `PetscObject`, `PetscObjectListAdd()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()`, 139*21532e8aSBarry Smith `PetscObjectListReverseFind()`, `PetscObjectListDuplicate()`, `PetscObject` 1401d0fab5eSBarry Smith @*/ 141d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectListDestroy(PetscObjectList *ifl) 142d71ae5a4SJacob Faibussowitsch { 1435f80ce2aSJacob Faibussowitsch PetscObjectList tmp, fl; 144e5c89e4eSSatish Balay 145e5c89e4eSSatish Balay PetscFunctionBegin; 1465f80ce2aSJacob Faibussowitsch PetscValidPointer(ifl, 1); 1475f80ce2aSJacob Faibussowitsch fl = *ifl; 1489c666560SBarry Smith while (fl) { 1499c666560SBarry Smith tmp = fl->next; 1509566063dSJacob Faibussowitsch if (!fl->skipdereference) PetscCall(PetscObjectDereference(fl->obj)); 1519566063dSJacob Faibussowitsch PetscCall(PetscFree(fl)); 1529c666560SBarry Smith fl = tmp; 153e5c89e4eSSatish Balay } 1540298fd71SBarry Smith *ifl = NULL; 1553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 156e5c89e4eSSatish Balay } 157e5c89e4eSSatish Balay 1581d0fab5eSBarry Smith /*@C 159*21532e8aSBarry Smith PetscObjectListFind - givn a name, find the matching object in a list 160e5c89e4eSSatish Balay 161e5c89e4eSSatish Balay Input Parameters: 162e5c89e4eSSatish Balay + fl - pointer to list 163e5c89e4eSSatish Balay - name - name string 164e5c89e4eSSatish Balay 1652fe279fdSBarry Smith Output Parameter: 1667243573dSPierre Jolivet . obj - the PETSc object 167e5c89e4eSSatish Balay 168b235ab32SBarry Smith Level: developer 169b235ab32SBarry Smith 170e5c89e4eSSatish Balay Notes: 171811af0c4SBarry Smith The name must have been registered with the `PetscObjectListAdd()` before calling this routine. 1723c0c59f3SBarry Smith 1733c0c59f3SBarry Smith The reference count of the object is not increased 174e5c89e4eSSatish Balay 175*21532e8aSBarry Smith .seealso: `PetscObjectListDestroy()`, `PetscObjectListAdd()`, `PetscObjectListDuplicate()`, `PetscObjectListReverseFind()`, `PetscObjectListDuplicate()`, 176*21532e8aSBarry Smith `PetscObjectList` 1771d0fab5eSBarry Smith @*/ 178d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectListFind(PetscObjectList fl, const char name[], PetscObject *obj) 179d71ae5a4SJacob Faibussowitsch { 180e5c89e4eSSatish Balay PetscFunctionBegin; 1815f80ce2aSJacob Faibussowitsch PetscValidPointer(obj, 3); 18202c9f0b5SLisandro Dalcin *obj = NULL; 183e5c89e4eSSatish Balay while (fl) { 1845f80ce2aSJacob Faibussowitsch PetscBool match; 1859566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, fl->name, &match)); 186e5c89e4eSSatish Balay if (match) { 187e5c89e4eSSatish Balay *obj = fl->obj; 188e5c89e4eSSatish Balay break; 189e5c89e4eSSatish Balay } 190e5c89e4eSSatish Balay fl = fl->next; 191e5c89e4eSSatish Balay } 1923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 193e5c89e4eSSatish Balay } 194e5c89e4eSSatish Balay 1951d0fab5eSBarry Smith /*@C 196140e18c1SBarry Smith PetscObjectListReverseFind - given a object, find the matching name if it exists 197e5c89e4eSSatish Balay 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 213*21532e8aSBarry Smith .seealso: `PetscObjectListDestroy()`, `PetscObjectListAdd()`, `PetscObjectListDuplicate()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()`, 214*21532e8aSBarry Smith `PetscObjectList` 2151d0fab5eSBarry Smith @*/ 216d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectListReverseFind(PetscObjectList fl, PetscObject obj, char **name, PetscBool *skipdereference) 217d71ae5a4SJacob Faibussowitsch { 218e5c89e4eSSatish Balay PetscFunctionBegin; 2195f80ce2aSJacob Faibussowitsch PetscValidPointer(name, 3); 2205f80ce2aSJacob Faibussowitsch if (skipdereference) PetscValidBoolPointer(skipdereference, 4); 22102c9f0b5SLisandro Dalcin *name = NULL; 222e5c89e4eSSatish Balay while (fl) { 223e5c89e4eSSatish Balay if (fl->obj == obj) { 224e5c89e4eSSatish Balay *name = fl->name; 225bfec8eecSBarry Smith if (skipdereference) *skipdereference = fl->skipdereference; 226e5c89e4eSSatish Balay break; 227e5c89e4eSSatish Balay } 228e5c89e4eSSatish Balay fl = fl->next; 229e5c89e4eSSatish Balay } 2303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 231e5c89e4eSSatish Balay } 232e5c89e4eSSatish Balay 2331d0fab5eSBarry Smith /*@C 2345e8f358bSStefano Zampini PetscObjectListDuplicate - Creates a new list from a given object list. 235e5c89e4eSSatish Balay 2362fe279fdSBarry Smith Input Parameter: 237e5c89e4eSSatish Balay . fl - pointer to list 238e5c89e4eSSatish Balay 2392fe279fdSBarry Smith Output Parameter: 240*21532e8aSBarry Smith . nl - the new list (should point to `NULL` to start, otherwise appends) 241e5c89e4eSSatish Balay 242b235ab32SBarry Smith Level: developer 243b235ab32SBarry Smith 244*21532e8aSBarry Smith .seealso: `PetscObjectListDestroy()`, `PetscObjectListAdd()`, `PetscObjectListReverseFind()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()`, 245*21532e8aSBarry Smith `PetscObjectList` 2461d0fab5eSBarry Smith @*/ 247d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectListDuplicate(PetscObjectList fl, PetscObjectList *nl) 248d71ae5a4SJacob Faibussowitsch { 249e5c89e4eSSatish Balay PetscFunctionBegin; 2505f80ce2aSJacob Faibussowitsch PetscValidPointer(nl, 2); 251e5c89e4eSSatish Balay while (fl) { 2529566063dSJacob Faibussowitsch PetscCall(PetscObjectListAdd(nl, fl->name, fl->obj)); 253e5c89e4eSSatish Balay fl = fl->next; 254e5c89e4eSSatish Balay } 2553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 256e5c89e4eSSatish Balay } 257