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 32db781477SPatrick Sanan .seealso: `PetscObjectListDestroy()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()`, `PetscObjectListReverseFind()`, `PetscObjectListDuplicate()`, `PetscObjectListAdd()` 336ba4bc90SBarry Smith @*/ 34d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectListRemoveReference(PetscObjectList *fl, const char name[]) 35d71ae5a4SJacob Faibussowitsch { 36140e18c1SBarry Smith PetscObjectList nlist; 376ba4bc90SBarry Smith PetscBool match; 386ba4bc90SBarry Smith 396ba4bc90SBarry Smith PetscFunctionBegin; 405f80ce2aSJacob Faibussowitsch PetscValidPointer(fl, 1); 415f80ce2aSJacob Faibussowitsch PetscValidCharPointer(name, 2); 4287130e5eSHong Zhang nlist = *fl; 436ba4bc90SBarry Smith while (nlist) { 449566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, nlist->name, &match)); 4500ac8be1SBarry Smith if (match) { /* found it in the list */ 469566063dSJacob Faibussowitsch if (!nlist->skipdereference) PetscCall(PetscObjectDereference(nlist->obj)); 476ba4bc90SBarry Smith nlist->skipdereference = PETSC_TRUE; 483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 496ba4bc90SBarry Smith } 506ba4bc90SBarry Smith nlist = nlist->next; 516ba4bc90SBarry Smith } 523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 536ba4bc90SBarry Smith } 546ba4bc90SBarry Smith 551d0fab5eSBarry Smith /*@C 56811af0c4SBarry Smith PetscObjectListAdd - Adds a new object to an `PetscObjectList` 57e5c89e4eSSatish Balay 581d0fab5eSBarry Smith Input Parameters: 591d0fab5eSBarry Smith + fl - the object list 601d0fab5eSBarry Smith . name - the name to use for the object 611d0fab5eSBarry Smith - obj - the object to attach 62e5c89e4eSSatish Balay 63b235ab32SBarry Smith Level: developer 64b235ab32SBarry Smith 6595452b02SPatrick Sanan Notes: 6695452b02SPatrick Sanan Replaces item if it is already in list. Removes item if you pass in a NULL object. 671d0fab5eSBarry Smith 68811af0c4SBarry Smith Use `PetscObjectListFind()` or `PetscObjectListReverseFind()` to get the object back 691d0fab5eSBarry Smith 70db781477SPatrick Sanan .seealso: `PetscObjectListDestroy()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()`, `PetscObjectListReverseFind()`, `PetscObjectListDuplicate()` 711d0fab5eSBarry Smith @*/ 72d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectListAdd(PetscObjectList *fl, const char name[], PetscObject obj) 73d71ae5a4SJacob Faibussowitsch { 74140e18c1SBarry Smith PetscObjectList olist, nlist, prev; 75ace3abfcSBarry Smith PetscBool match; 76e5c89e4eSSatish Balay 77e5c89e4eSSatish Balay PetscFunctionBegin; 785f80ce2aSJacob Faibussowitsch PetscValidPointer(fl, 1); 79e5c89e4eSSatish Balay if (!obj) { /* this means remove from list if it is there */ 809371c9d4SSatish Balay nlist = *fl; 819371c9d4SSatish Balay prev = NULL; 82e5c89e4eSSatish Balay while (nlist) { 839566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, nlist->name, &match)); 84e5c89e4eSSatish Balay if (match) { /* found it already in the list */ 854a0791bcSMatthew G. Knepley /* Remove it first to prevent circular derefs */ 86e5c89e4eSSatish Balay if (prev) prev->next = nlist->next; 87a297a907SKarl Rupp else if (nlist->next) *fl = nlist->next; 8802c9f0b5SLisandro Dalcin else *fl = NULL; 899566063dSJacob Faibussowitsch if (!nlist->skipdereference) PetscCall(PetscObjectDereference(nlist->obj)); 909566063dSJacob Faibussowitsch PetscCall(PetscFree(nlist)); 913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 92e5c89e4eSSatish Balay } 93e5c89e4eSSatish Balay prev = nlist; 94e5c89e4eSSatish Balay nlist = nlist->next; 95e5c89e4eSSatish Balay } 963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); /* did not find it to remove */ 97e5c89e4eSSatish Balay } 98e5c89e4eSSatish Balay /* look for it already in list */ 99e5c89e4eSSatish Balay nlist = *fl; 100e5c89e4eSSatish Balay while (nlist) { 1019566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, nlist->name, &match)); 102e5c89e4eSSatish Balay if (match) { /* found it in the list */ 1039566063dSJacob Faibussowitsch PetscCall(PetscObjectReference(obj)); 1049566063dSJacob Faibussowitsch if (!nlist->skipdereference) PetscCall(PetscObjectDereference(nlist->obj)); 10500ac8be1SBarry Smith nlist->skipdereference = PETSC_FALSE; 106e5c89e4eSSatish Balay nlist->obj = obj; 1073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 108e5c89e4eSSatish Balay } 109e5c89e4eSSatish Balay nlist = nlist->next; 110e5c89e4eSSatish Balay } 111e5c89e4eSSatish Balay 112e5c89e4eSSatish Balay /* add it to list, because it was not already there */ 1139566063dSJacob Faibussowitsch PetscCall(PetscNew(&olist)); 11402c9f0b5SLisandro Dalcin olist->next = NULL; 115e5c89e4eSSatish Balay olist->obj = obj; 116a297a907SKarl Rupp 1179566063dSJacob Faibussowitsch PetscCall(PetscObjectReference(obj)); 118c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(olist->name, name, sizeof(olist->name))); 119e5c89e4eSSatish Balay 120a297a907SKarl Rupp if (!*fl) *fl = olist; 1219371c9d4SSatish Balay else { /* go to end of list */ nlist = *fl; 1225f80ce2aSJacob Faibussowitsch while (nlist->next) nlist = nlist->next; 123e5c89e4eSSatish Balay nlist->next = olist; 124e5c89e4eSSatish Balay } 1253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 126e5c89e4eSSatish Balay } 127e5c89e4eSSatish Balay 1281d0fab5eSBarry Smith /*@C 129140e18c1SBarry Smith PetscObjectListDestroy - Destroy a list of objects 130e5c89e4eSSatish Balay 131e5c89e4eSSatish Balay Input Parameter: 1326bf464f9SBarry Smith . ifl - pointer to list 1331d0fab5eSBarry Smith 134b235ab32SBarry Smith Level: developer 135b235ab32SBarry Smith 136db781477SPatrick Sanan .seealso: `PetscObjectListAdd()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()`, `PetscObjectListReverseFind()`, `PetscObjectListDuplicate()` 1371d0fab5eSBarry Smith @*/ 138d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectListDestroy(PetscObjectList *ifl) 139d71ae5a4SJacob Faibussowitsch { 1405f80ce2aSJacob Faibussowitsch PetscObjectList tmp, fl; 141e5c89e4eSSatish Balay 142e5c89e4eSSatish Balay PetscFunctionBegin; 1435f80ce2aSJacob Faibussowitsch PetscValidPointer(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 156140e18c1SBarry Smith PetscObjectListFind - givn a name, find the matching object 157e5c89e4eSSatish Balay 158e5c89e4eSSatish Balay Input Parameters: 159e5c89e4eSSatish Balay + fl - pointer to list 160e5c89e4eSSatish Balay - name - name string 161e5c89e4eSSatish Balay 162*2fe279fdSBarry Smith Output Parameter: 1637243573dSPierre Jolivet . obj - the PETSc object 164e5c89e4eSSatish Balay 165b235ab32SBarry Smith Level: developer 166b235ab32SBarry Smith 167e5c89e4eSSatish Balay Notes: 168811af0c4SBarry Smith The name must have been registered with the `PetscObjectListAdd()` before calling this routine. 1693c0c59f3SBarry Smith 1703c0c59f3SBarry Smith The reference count of the object is not increased 171e5c89e4eSSatish Balay 172db781477SPatrick Sanan .seealso: `PetscObjectListDestroy()`, `PetscObjectListAdd()`, `PetscObjectListDuplicate()`, `PetscObjectListReverseFind()`, `PetscObjectListDuplicate()` 1731d0fab5eSBarry Smith @*/ 174d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectListFind(PetscObjectList fl, const char name[], PetscObject *obj) 175d71ae5a4SJacob Faibussowitsch { 176e5c89e4eSSatish Balay PetscFunctionBegin; 1775f80ce2aSJacob Faibussowitsch PetscValidPointer(obj, 3); 17802c9f0b5SLisandro Dalcin *obj = NULL; 179e5c89e4eSSatish Balay while (fl) { 1805f80ce2aSJacob Faibussowitsch PetscBool match; 1819566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, fl->name, &match)); 182e5c89e4eSSatish Balay if (match) { 183e5c89e4eSSatish Balay *obj = fl->obj; 184e5c89e4eSSatish Balay break; 185e5c89e4eSSatish Balay } 186e5c89e4eSSatish Balay fl = fl->next; 187e5c89e4eSSatish Balay } 1883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 189e5c89e4eSSatish Balay } 190e5c89e4eSSatish Balay 1911d0fab5eSBarry Smith /*@C 192140e18c1SBarry Smith PetscObjectListReverseFind - given a object, find the matching name if it exists 193e5c89e4eSSatish Balay 194e5c89e4eSSatish Balay Input Parameters: 195e5c89e4eSSatish Balay + fl - pointer to list 1967243573dSPierre Jolivet - obj - the PETSc object 197e5c89e4eSSatish Balay 198e5c89e4eSSatish Balay Output Parameters: 199bfec8eecSBarry Smith + name - name string 2005e8f358bSStefano Zampini - skipdereference - if the object is in list but does not have the increased reference count for a circular dependency 201e5c89e4eSSatish Balay 202b235ab32SBarry Smith Level: developer 203b235ab32SBarry Smith 204e5c89e4eSSatish Balay Notes: 205811af0c4SBarry Smith The name must have been registered with the `PetscObjectListAdd()` before calling this routine. 2063c0c59f3SBarry Smith 2073c0c59f3SBarry Smith The reference count of the object is not increased 208e5c89e4eSSatish Balay 209db781477SPatrick Sanan .seealso: `PetscObjectListDestroy()`, `PetscObjectListAdd()`, `PetscObjectListDuplicate()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()` 2101d0fab5eSBarry Smith @*/ 211d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectListReverseFind(PetscObjectList fl, PetscObject obj, char **name, PetscBool *skipdereference) 212d71ae5a4SJacob Faibussowitsch { 213e5c89e4eSSatish Balay PetscFunctionBegin; 2145f80ce2aSJacob Faibussowitsch PetscValidPointer(name, 3); 2155f80ce2aSJacob Faibussowitsch if (skipdereference) PetscValidBoolPointer(skipdereference, 4); 21602c9f0b5SLisandro Dalcin *name = NULL; 217e5c89e4eSSatish Balay while (fl) { 218e5c89e4eSSatish Balay if (fl->obj == obj) { 219e5c89e4eSSatish Balay *name = fl->name; 220bfec8eecSBarry Smith if (skipdereference) *skipdereference = fl->skipdereference; 221e5c89e4eSSatish Balay break; 222e5c89e4eSSatish Balay } 223e5c89e4eSSatish Balay fl = fl->next; 224e5c89e4eSSatish Balay } 2253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 226e5c89e4eSSatish Balay } 227e5c89e4eSSatish Balay 2281d0fab5eSBarry Smith /*@C 2295e8f358bSStefano Zampini PetscObjectListDuplicate - Creates a new list from a given object list. 230e5c89e4eSSatish Balay 231*2fe279fdSBarry Smith Input Parameter: 232e5c89e4eSSatish Balay . fl - pointer to list 233e5c89e4eSSatish Balay 234*2fe279fdSBarry Smith Output Parameter: 235e5c89e4eSSatish Balay . nl - the new list (should point to 0 to start, otherwise appends) 236e5c89e4eSSatish Balay 237b235ab32SBarry Smith Level: developer 238b235ab32SBarry Smith 239db781477SPatrick Sanan .seealso: `PetscObjectListDestroy()`, `PetscObjectListAdd()`, `PetscObjectListReverseFind()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()` 2401d0fab5eSBarry Smith @*/ 241d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectListDuplicate(PetscObjectList fl, PetscObjectList *nl) 242d71ae5a4SJacob Faibussowitsch { 243e5c89e4eSSatish Balay PetscFunctionBegin; 2445f80ce2aSJacob Faibussowitsch PetscValidPointer(nl, 2); 245e5c89e4eSSatish Balay while (fl) { 2469566063dSJacob Faibussowitsch PetscCall(PetscObjectListAdd(nl, fl->name, fl->obj)); 247e5c89e4eSSatish Balay fl = fl->next; 248e5c89e4eSSatish Balay } 2493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 250e5c89e4eSSatish Balay } 251