xref: /petsc/src/sys/objects/olist.c (revision 9371c9d470a9602b6d10a8bf50c9b2280a79e45a)
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
16140e18c1SBarry 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:
2595452b02SPatrick Sanan     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 
296ba4bc90SBarry Smith       Developer Note: this is to handle some cases that otherwise would result in having circular references so reference counts never got to zero
306ba4bc90SBarry Smith 
31db781477SPatrick Sanan .seealso: `PetscObjectListDestroy()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()`, `PetscObjectListReverseFind()`, `PetscObjectListDuplicate()`, `PetscObjectListAdd()`
326ba4bc90SBarry Smith 
336ba4bc90SBarry Smith @*/
34*9371c9d4SSatish Balay PetscErrorCode PetscObjectListRemoveReference(PetscObjectList *fl, const char name[]) {
35140e18c1SBarry Smith   PetscObjectList nlist;
366ba4bc90SBarry Smith   PetscBool       match;
376ba4bc90SBarry Smith 
386ba4bc90SBarry Smith   PetscFunctionBegin;
395f80ce2aSJacob Faibussowitsch   PetscValidPointer(fl, 1);
405f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(name, 2);
4187130e5eSHong Zhang   nlist = *fl;
426ba4bc90SBarry Smith   while (nlist) {
439566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, nlist->name, &match));
4400ac8be1SBarry Smith     if (match) { /* found it in the list */
459566063dSJacob Faibussowitsch       if (!nlist->skipdereference) PetscCall(PetscObjectDereference(nlist->obj));
466ba4bc90SBarry Smith       nlist->skipdereference = PETSC_TRUE;
476ba4bc90SBarry Smith       PetscFunctionReturn(0);
486ba4bc90SBarry Smith     }
496ba4bc90SBarry Smith     nlist = nlist->next;
506ba4bc90SBarry Smith   }
516ba4bc90SBarry Smith   PetscFunctionReturn(0);
526ba4bc90SBarry Smith }
536ba4bc90SBarry Smith 
541d0fab5eSBarry Smith /*@C
55140e18c1SBarry Smith      PetscObjectListAdd - Adds a new object to an PetscObjectList
56e5c89e4eSSatish Balay 
571d0fab5eSBarry Smith     Input Parameters:
581d0fab5eSBarry Smith +     fl - the object list
591d0fab5eSBarry Smith .     name - the name to use for the object
601d0fab5eSBarry Smith -     obj - the object to attach
61e5c89e4eSSatish Balay 
62b235ab32SBarry Smith     Level: developer
63b235ab32SBarry Smith 
6495452b02SPatrick Sanan        Notes:
6595452b02SPatrick Sanan     Replaces item if it is already in list. Removes item if you pass in a NULL object.
661d0fab5eSBarry Smith 
67140e18c1SBarry Smith         Use PetscObjectListFind() or PetscObjectListReverseFind() to get the object back
681d0fab5eSBarry Smith 
69db781477SPatrick Sanan .seealso: `PetscObjectListDestroy()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()`, `PetscObjectListReverseFind()`, `PetscObjectListDuplicate()`
701d0fab5eSBarry Smith 
711d0fab5eSBarry Smith @*/
72*9371c9d4SSatish Balay PetscErrorCode PetscObjectListAdd(PetscObjectList *fl, const char name[], PetscObject obj) {
73140e18c1SBarry Smith   PetscObjectList olist, nlist, prev;
74ace3abfcSBarry Smith   PetscBool       match;
75e5c89e4eSSatish Balay 
76e5c89e4eSSatish Balay   PetscFunctionBegin;
775f80ce2aSJacob Faibussowitsch   PetscValidPointer(fl, 1);
78e5c89e4eSSatish Balay   if (!obj) { /* this means remove from list if it is there */
79*9371c9d4SSatish Balay     nlist = *fl;
80*9371c9d4SSatish Balay     prev  = NULL;
81e5c89e4eSSatish Balay     while (nlist) {
829566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, nlist->name, &match));
83e5c89e4eSSatish Balay       if (match) { /* found it already in the list */
844a0791bcSMatthew G. Knepley         /* Remove it first to prevent circular derefs */
85e5c89e4eSSatish Balay         if (prev) prev->next = nlist->next;
86a297a907SKarl Rupp         else if (nlist->next) *fl = nlist->next;
8702c9f0b5SLisandro Dalcin         else *fl = NULL;
889566063dSJacob Faibussowitsch         if (!nlist->skipdereference) PetscCall(PetscObjectDereference(nlist->obj));
899566063dSJacob Faibussowitsch         PetscCall(PetscFree(nlist));
90e5c89e4eSSatish Balay         PetscFunctionReturn(0);
91e5c89e4eSSatish Balay       }
92e5c89e4eSSatish Balay       prev  = nlist;
93e5c89e4eSSatish Balay       nlist = nlist->next;
94e5c89e4eSSatish Balay     }
95e5c89e4eSSatish Balay     PetscFunctionReturn(0); /* did not find it to remove */
96e5c89e4eSSatish Balay   }
97e5c89e4eSSatish Balay   /* look for it already in list */
98e5c89e4eSSatish Balay   nlist = *fl;
99e5c89e4eSSatish Balay   while (nlist) {
1009566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, nlist->name, &match));
101e5c89e4eSSatish Balay     if (match) { /* found it in the list */
1029566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference(obj));
1039566063dSJacob Faibussowitsch       if (!nlist->skipdereference) PetscCall(PetscObjectDereference(nlist->obj));
10400ac8be1SBarry Smith       nlist->skipdereference = PETSC_FALSE;
105e5c89e4eSSatish Balay       nlist->obj             = obj;
106e5c89e4eSSatish Balay       PetscFunctionReturn(0);
107e5c89e4eSSatish Balay     }
108e5c89e4eSSatish Balay     nlist = nlist->next;
109e5c89e4eSSatish Balay   }
110e5c89e4eSSatish Balay 
111e5c89e4eSSatish Balay   /* add it to list, because it was not already there */
1129566063dSJacob Faibussowitsch   PetscCall(PetscNew(&olist));
11302c9f0b5SLisandro Dalcin   olist->next = NULL;
114e5c89e4eSSatish Balay   olist->obj  = obj;
115a297a907SKarl Rupp 
1169566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference(obj));
1179566063dSJacob Faibussowitsch   PetscCall(PetscStrcpy(olist->name, name));
118e5c89e4eSSatish Balay 
119a297a907SKarl Rupp   if (!*fl) *fl = olist;
120*9371c9d4SSatish Balay   else { /* go to end of list */ nlist = *fl;
1215f80ce2aSJacob Faibussowitsch     while (nlist->next) nlist = nlist->next;
122e5c89e4eSSatish Balay     nlist->next = olist;
123e5c89e4eSSatish Balay   }
124e5c89e4eSSatish Balay   PetscFunctionReturn(0);
125e5c89e4eSSatish Balay }
126e5c89e4eSSatish Balay 
1271d0fab5eSBarry Smith /*@C
128140e18c1SBarry Smith     PetscObjectListDestroy - Destroy a list of objects
129e5c89e4eSSatish Balay 
130e5c89e4eSSatish Balay     Input Parameter:
1316bf464f9SBarry Smith .   ifl   - pointer to list
1321d0fab5eSBarry Smith 
133b235ab32SBarry Smith     Level: developer
134b235ab32SBarry Smith 
135db781477SPatrick Sanan .seealso: `PetscObjectListAdd()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()`, `PetscObjectListReverseFind()`, `PetscObjectListDuplicate()`
1361d0fab5eSBarry Smith 
1371d0fab5eSBarry Smith @*/
138*9371c9d4SSatish Balay PetscErrorCode PetscObjectListDestroy(PetscObjectList *ifl) {
1395f80ce2aSJacob Faibussowitsch   PetscObjectList tmp, fl;
140e5c89e4eSSatish Balay 
141e5c89e4eSSatish Balay   PetscFunctionBegin;
1425f80ce2aSJacob Faibussowitsch   PetscValidPointer(ifl, 1);
1435f80ce2aSJacob Faibussowitsch   fl = *ifl;
1449c666560SBarry Smith   while (fl) {
1459c666560SBarry Smith     tmp = fl->next;
1469566063dSJacob Faibussowitsch     if (!fl->skipdereference) PetscCall(PetscObjectDereference(fl->obj));
1479566063dSJacob Faibussowitsch     PetscCall(PetscFree(fl));
1489c666560SBarry Smith     fl = tmp;
149e5c89e4eSSatish Balay   }
1500298fd71SBarry Smith   *ifl = NULL;
151e5c89e4eSSatish Balay   PetscFunctionReturn(0);
152e5c89e4eSSatish Balay }
153e5c89e4eSSatish Balay 
1541d0fab5eSBarry Smith /*@C
155140e18c1SBarry Smith     PetscObjectListFind - givn a name, find the matching object
156e5c89e4eSSatish Balay 
157e5c89e4eSSatish Balay     Input Parameters:
158e5c89e4eSSatish Balay +   fl   - pointer to list
159e5c89e4eSSatish Balay -   name - name string
160e5c89e4eSSatish Balay 
161e5c89e4eSSatish Balay     Output Parameters:
1627243573dSPierre Jolivet .   obj - the PETSc object
163e5c89e4eSSatish Balay 
164b235ab32SBarry Smith     Level: developer
165b235ab32SBarry Smith 
166e5c89e4eSSatish Balay     Notes:
167140e18c1SBarry Smith     The name must have been registered with the PetscObjectListAdd() before calling this routine.
1683c0c59f3SBarry Smith 
1693c0c59f3SBarry Smith     The reference count of the object is not increased
170e5c89e4eSSatish Balay 
171db781477SPatrick Sanan .seealso: `PetscObjectListDestroy()`, `PetscObjectListAdd()`, `PetscObjectListDuplicate()`, `PetscObjectListReverseFind()`, `PetscObjectListDuplicate()`
172e5c89e4eSSatish Balay 
1731d0fab5eSBarry Smith @*/
174*9371c9d4SSatish Balay PetscErrorCode PetscObjectListFind(PetscObjectList fl, const char name[], PetscObject *obj) {
175e5c89e4eSSatish Balay   PetscFunctionBegin;
1765f80ce2aSJacob Faibussowitsch   PetscValidPointer(obj, 3);
17702c9f0b5SLisandro Dalcin   *obj = NULL;
178e5c89e4eSSatish Balay   while (fl) {
1795f80ce2aSJacob Faibussowitsch     PetscBool match;
1809566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, fl->name, &match));
181e5c89e4eSSatish Balay     if (match) {
182e5c89e4eSSatish Balay       *obj = fl->obj;
183e5c89e4eSSatish Balay       break;
184e5c89e4eSSatish Balay     }
185e5c89e4eSSatish Balay     fl = fl->next;
186e5c89e4eSSatish Balay   }
187e5c89e4eSSatish Balay   PetscFunctionReturn(0);
188e5c89e4eSSatish Balay }
189e5c89e4eSSatish Balay 
1901d0fab5eSBarry Smith /*@C
191140e18c1SBarry Smith     PetscObjectListReverseFind - given a object, find the matching name if it exists
192e5c89e4eSSatish Balay 
193e5c89e4eSSatish Balay     Input Parameters:
194e5c89e4eSSatish Balay +   fl   - pointer to list
1957243573dSPierre Jolivet -   obj - the PETSc object
196e5c89e4eSSatish Balay 
197e5c89e4eSSatish Balay     Output Parameters:
198bfec8eecSBarry Smith +  name - name string
1995e8f358bSStefano Zampini -  skipdereference - if the object is in list but does not have the increased reference count for a circular dependency
200e5c89e4eSSatish Balay 
201b235ab32SBarry Smith     Level: developer
202b235ab32SBarry Smith 
203e5c89e4eSSatish Balay     Notes:
204140e18c1SBarry Smith     The name must have been registered with the PetscObjectListAdd() before calling this routine.
2053c0c59f3SBarry Smith 
2063c0c59f3SBarry Smith     The reference count of the object is not increased
207e5c89e4eSSatish Balay 
208db781477SPatrick Sanan .seealso: `PetscObjectListDestroy()`, `PetscObjectListAdd()`, `PetscObjectListDuplicate()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()`
209e5c89e4eSSatish Balay 
2101d0fab5eSBarry Smith @*/
211*9371c9d4SSatish Balay PetscErrorCode PetscObjectListReverseFind(PetscObjectList fl, PetscObject obj, char **name, PetscBool *skipdereference) {
212e5c89e4eSSatish Balay   PetscFunctionBegin;
2135f80ce2aSJacob Faibussowitsch   PetscValidPointer(name, 3);
2145f80ce2aSJacob Faibussowitsch   if (skipdereference) PetscValidBoolPointer(skipdereference, 4);
21502c9f0b5SLisandro Dalcin   *name = NULL;
216e5c89e4eSSatish Balay   while (fl) {
217e5c89e4eSSatish Balay     if (fl->obj == obj) {
218e5c89e4eSSatish Balay       *name = fl->name;
219bfec8eecSBarry Smith       if (skipdereference) *skipdereference = fl->skipdereference;
220e5c89e4eSSatish Balay       break;
221e5c89e4eSSatish Balay     }
222e5c89e4eSSatish Balay     fl = fl->next;
223e5c89e4eSSatish Balay   }
224e5c89e4eSSatish Balay   PetscFunctionReturn(0);
225e5c89e4eSSatish Balay }
226e5c89e4eSSatish Balay 
2271d0fab5eSBarry Smith /*@C
2285e8f358bSStefano Zampini     PetscObjectListDuplicate - Creates a new list from a given object list.
229e5c89e4eSSatish Balay 
230e5c89e4eSSatish Balay     Input Parameters:
231e5c89e4eSSatish Balay .   fl   - pointer to list
232e5c89e4eSSatish Balay 
233e5c89e4eSSatish Balay     Output Parameters:
234e5c89e4eSSatish Balay .   nl - the new list (should point to 0 to start, otherwise appends)
235e5c89e4eSSatish Balay 
236b235ab32SBarry Smith     Level: developer
237b235ab32SBarry Smith 
238db781477SPatrick Sanan .seealso: `PetscObjectListDestroy()`, `PetscObjectListAdd()`, `PetscObjectListReverseFind()`, `PetscObjectListFind()`, `PetscObjectListDuplicate()`
239e5c89e4eSSatish Balay 
2401d0fab5eSBarry Smith @*/
241*9371c9d4SSatish Balay PetscErrorCode PetscObjectListDuplicate(PetscObjectList fl, PetscObjectList *nl) {
242e5c89e4eSSatish Balay   PetscFunctionBegin;
2435f80ce2aSJacob Faibussowitsch   PetscValidPointer(nl, 2);
244e5c89e4eSSatish Balay   while (fl) {
2459566063dSJacob Faibussowitsch     PetscCall(PetscObjectListAdd(nl, fl->name, fl->obj));
246e5c89e4eSSatish Balay     fl = fl->next;
247e5c89e4eSSatish Balay   }
248e5c89e4eSSatish Balay   PetscFunctionReturn(0);
249e5c89e4eSSatish Balay }
250