xref: /petsc/src/sys/objects/olist.c (revision aec76313382a76d73a95f2051cbe4b1eab55c1c7)
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