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