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