xref: /petsc/src/sys/objects/olist.c (revision 5f80ce2ab25dff0f4601e710601cbbcecf323266)
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 */
6*5f80ce2aSJacob 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 
31140e18c1SBarry Smith .seealso: PetscObjectListDestroy(), PetscObjectListFind(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate(), PetscObjectListAdd()
326ba4bc90SBarry Smith 
336ba4bc90SBarry Smith @*/
34140e18c1SBarry Smith PetscErrorCode  PetscObjectListRemoveReference(PetscObjectList *fl,const char name[])
356ba4bc90SBarry Smith {
36140e18c1SBarry Smith   PetscObjectList nlist;
376ba4bc90SBarry Smith   PetscBool       match;
386ba4bc90SBarry Smith 
396ba4bc90SBarry Smith   PetscFunctionBegin;
40*5f80ce2aSJacob Faibussowitsch   PetscValidPointer(fl,1);
41*5f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(name,2);
4287130e5eSHong Zhang   nlist = *fl;
436ba4bc90SBarry Smith   while (nlist) {
44*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcmp(name,nlist->name,&match));
4500ac8be1SBarry Smith     if (match) { /* found it in the list */
46*5f80ce2aSJacob Faibussowitsch       if (!nlist->skipdereference) CHKERRQ(PetscObjectDereference(nlist->obj));
476ba4bc90SBarry Smith       nlist->skipdereference = PETSC_TRUE;
486ba4bc90SBarry Smith       PetscFunctionReturn(0);
496ba4bc90SBarry Smith     }
506ba4bc90SBarry Smith     nlist = nlist->next;
516ba4bc90SBarry Smith   }
526ba4bc90SBarry Smith   PetscFunctionReturn(0);
536ba4bc90SBarry Smith }
546ba4bc90SBarry Smith 
551d0fab5eSBarry Smith /*@C
56140e18c1SBarry 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 
68140e18c1SBarry Smith         Use PetscObjectListFind() or PetscObjectListReverseFind() to get the object back
691d0fab5eSBarry Smith 
70140e18c1SBarry Smith .seealso: PetscObjectListDestroy(), PetscObjectListFind(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate()
711d0fab5eSBarry Smith 
721d0fab5eSBarry Smith @*/
73140e18c1SBarry Smith PetscErrorCode  PetscObjectListAdd(PetscObjectList *fl,const char name[],PetscObject obj)
74e5c89e4eSSatish Balay {
75140e18c1SBarry Smith   PetscObjectList olist,nlist,prev;
76ace3abfcSBarry Smith   PetscBool       match;
77e5c89e4eSSatish Balay 
78e5c89e4eSSatish Balay   PetscFunctionBegin;
79*5f80ce2aSJacob Faibussowitsch   PetscValidPointer(fl,1);
80e5c89e4eSSatish Balay   if (!obj) { /* this means remove from list if it is there */
8102c9f0b5SLisandro Dalcin     nlist = *fl; prev = NULL;
82e5c89e4eSSatish Balay     while (nlist) {
83*5f80ce2aSJacob Faibussowitsch       CHKERRQ(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;
89*5f80ce2aSJacob Faibussowitsch         if (!nlist->skipdereference) CHKERRQ(PetscObjectDereference(nlist->obj));
90*5f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscFree(nlist));
91e5c89e4eSSatish Balay         PetscFunctionReturn(0);
92e5c89e4eSSatish Balay       }
93e5c89e4eSSatish Balay       prev  = nlist;
94e5c89e4eSSatish Balay       nlist = nlist->next;
95e5c89e4eSSatish Balay     }
96e5c89e4eSSatish Balay     PetscFunctionReturn(0); /* did not find it to remove */
97e5c89e4eSSatish Balay   }
98e5c89e4eSSatish Balay   /* look for it already in list */
99e5c89e4eSSatish Balay   nlist = *fl;
100e5c89e4eSSatish Balay   while (nlist) {
101*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcmp(name,nlist->name,&match));
102e5c89e4eSSatish Balay     if (match) {  /* found it in the list */
103*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectReference(obj));
104*5f80ce2aSJacob Faibussowitsch       if (!nlist->skipdereference) CHKERRQ(PetscObjectDereference(nlist->obj));
10500ac8be1SBarry Smith       nlist->skipdereference = PETSC_FALSE;
106e5c89e4eSSatish Balay       nlist->obj             = obj;
107e5c89e4eSSatish Balay       PetscFunctionReturn(0);
108e5c89e4eSSatish Balay     }
109e5c89e4eSSatish Balay     nlist = nlist->next;
110e5c89e4eSSatish Balay   }
111e5c89e4eSSatish Balay 
112e5c89e4eSSatish Balay   /* add it to list, because it was not already there */
113*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscNew(&olist));
11402c9f0b5SLisandro Dalcin   olist->next = NULL;
115e5c89e4eSSatish Balay   olist->obj  = obj;
116a297a907SKarl Rupp 
117*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectReference(obj));
118*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcpy(olist->name,name));
119e5c89e4eSSatish Balay 
120a297a907SKarl Rupp   if (!*fl) *fl = olist;
121a297a907SKarl Rupp   else { /* go to end of list */
122e5c89e4eSSatish Balay     nlist = *fl;
123*5f80ce2aSJacob Faibussowitsch     while (nlist->next) nlist = nlist->next;
124e5c89e4eSSatish Balay     nlist->next = olist;
125e5c89e4eSSatish Balay   }
126e5c89e4eSSatish Balay   PetscFunctionReturn(0);
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 
137140e18c1SBarry Smith .seealso: PetscObjectListAdd(), PetscObjectListFind(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate()
1381d0fab5eSBarry Smith 
1391d0fab5eSBarry Smith @*/
140140e18c1SBarry Smith PetscErrorCode  PetscObjectListDestroy(PetscObjectList *ifl)
141e5c89e4eSSatish Balay {
142*5f80ce2aSJacob Faibussowitsch   PetscObjectList tmp,fl;
143e5c89e4eSSatish Balay 
144e5c89e4eSSatish Balay   PetscFunctionBegin;
145*5f80ce2aSJacob Faibussowitsch   PetscValidPointer(ifl,1);
146*5f80ce2aSJacob Faibussowitsch   fl = *ifl;
1479c666560SBarry Smith   while (fl) {
1489c666560SBarry Smith     tmp = fl->next;
149*5f80ce2aSJacob Faibussowitsch     if (!fl->skipdereference) CHKERRQ(PetscObjectDereference(fl->obj));
150*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(fl));
1519c666560SBarry Smith     fl   = tmp;
152e5c89e4eSSatish Balay   }
1530298fd71SBarry Smith   *ifl = NULL;
154e5c89e4eSSatish Balay   PetscFunctionReturn(0);
155e5c89e4eSSatish Balay }
156e5c89e4eSSatish Balay 
1571d0fab5eSBarry Smith /*@C
158140e18c1SBarry Smith     PetscObjectListFind - givn a name, find the matching object
159e5c89e4eSSatish Balay 
160e5c89e4eSSatish Balay     Input Parameters:
161e5c89e4eSSatish Balay +   fl   - pointer to list
162e5c89e4eSSatish Balay -   name - name string
163e5c89e4eSSatish Balay 
164e5c89e4eSSatish Balay     Output Parameters:
1657243573dSPierre Jolivet .   obj - the PETSc object
166e5c89e4eSSatish Balay 
167b235ab32SBarry Smith     Level: developer
168b235ab32SBarry Smith 
169e5c89e4eSSatish Balay     Notes:
170140e18c1SBarry 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 
174140e18c1SBarry Smith .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate()
175e5c89e4eSSatish Balay 
1761d0fab5eSBarry Smith @*/
177140e18c1SBarry Smith PetscErrorCode  PetscObjectListFind(PetscObjectList fl,const char name[],PetscObject *obj)
178e5c89e4eSSatish Balay {
179e5c89e4eSSatish Balay   PetscFunctionBegin;
180*5f80ce2aSJacob Faibussowitsch   PetscValidPointer(obj,3);
18102c9f0b5SLisandro Dalcin   *obj = NULL;
182e5c89e4eSSatish Balay   while (fl) {
183*5f80ce2aSJacob Faibussowitsch     PetscBool match;
184*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcmp(name,fl->name,&match));
185e5c89e4eSSatish Balay     if (match) {
186e5c89e4eSSatish Balay       *obj = fl->obj;
187e5c89e4eSSatish Balay       break;
188e5c89e4eSSatish Balay     }
189e5c89e4eSSatish Balay     fl = fl->next;
190e5c89e4eSSatish Balay   }
191e5c89e4eSSatish Balay   PetscFunctionReturn(0);
192e5c89e4eSSatish Balay }
193e5c89e4eSSatish Balay 
1941d0fab5eSBarry Smith /*@C
195140e18c1SBarry Smith     PetscObjectListReverseFind - given a object, find the matching name if it exists
196e5c89e4eSSatish Balay 
197e5c89e4eSSatish Balay     Input Parameters:
198e5c89e4eSSatish Balay +   fl   - pointer to list
1997243573dSPierre Jolivet -   obj - the PETSc object
200e5c89e4eSSatish Balay 
201e5c89e4eSSatish Balay     Output Parameters:
202bfec8eecSBarry Smith +  name - name string
2035e8f358bSStefano Zampini -  skipdereference - if the object is in list but does not have the increased reference count for a circular dependency
204e5c89e4eSSatish Balay 
205b235ab32SBarry Smith     Level: developer
206b235ab32SBarry Smith 
207e5c89e4eSSatish Balay     Notes:
208140e18c1SBarry Smith     The name must have been registered with the PetscObjectListAdd() before calling this routine.
2093c0c59f3SBarry Smith 
2103c0c59f3SBarry Smith     The reference count of the object is not increased
211e5c89e4eSSatish Balay 
212140e18c1SBarry Smith .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListFind(), PetscObjectListDuplicate()
213e5c89e4eSSatish Balay 
2141d0fab5eSBarry Smith @*/
215140e18c1SBarry Smith PetscErrorCode  PetscObjectListReverseFind(PetscObjectList fl,PetscObject obj,char **name,PetscBool *skipdereference)
216e5c89e4eSSatish Balay {
217e5c89e4eSSatish Balay   PetscFunctionBegin;
218*5f80ce2aSJacob Faibussowitsch   PetscValidPointer(name,3);
219*5f80ce2aSJacob Faibussowitsch   if (skipdereference) PetscValidBoolPointer(skipdereference,4);
22002c9f0b5SLisandro Dalcin   *name = NULL;
221e5c89e4eSSatish Balay   while (fl) {
222e5c89e4eSSatish Balay     if (fl->obj == obj) {
223e5c89e4eSSatish Balay       *name = fl->name;
224bfec8eecSBarry Smith       if (skipdereference) *skipdereference = fl->skipdereference;
225e5c89e4eSSatish Balay       break;
226e5c89e4eSSatish Balay     }
227e5c89e4eSSatish Balay     fl = fl->next;
228e5c89e4eSSatish Balay   }
229e5c89e4eSSatish Balay   PetscFunctionReturn(0);
230e5c89e4eSSatish Balay }
231e5c89e4eSSatish Balay 
2321d0fab5eSBarry Smith /*@C
2335e8f358bSStefano Zampini     PetscObjectListDuplicate - Creates a new list from a given object list.
234e5c89e4eSSatish Balay 
235e5c89e4eSSatish Balay     Input Parameters:
236e5c89e4eSSatish Balay .   fl   - pointer to list
237e5c89e4eSSatish Balay 
238e5c89e4eSSatish Balay     Output Parameters:
239e5c89e4eSSatish Balay .   nl - the new list (should point to 0 to start, otherwise appends)
240e5c89e4eSSatish Balay 
241b235ab32SBarry Smith     Level: developer
242b235ab32SBarry Smith 
243140e18c1SBarry Smith .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListReverseFind(), PetscObjectListFind(), PetscObjectListDuplicate()
244e5c89e4eSSatish Balay 
2451d0fab5eSBarry Smith @*/
246140e18c1SBarry Smith PetscErrorCode  PetscObjectListDuplicate(PetscObjectList fl,PetscObjectList *nl)
247e5c89e4eSSatish Balay {
248e5c89e4eSSatish Balay   PetscFunctionBegin;
249*5f80ce2aSJacob Faibussowitsch   PetscValidPointer(nl,2);
250e5c89e4eSSatish Balay   while (fl) {
251*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectListAdd(nl,fl->name,fl->obj));
252e5c89e4eSSatish Balay     fl = fl->next;
253e5c89e4eSSatish Balay   }
254e5c89e4eSSatish Balay   PetscFunctionReturn(0);
255e5c89e4eSSatish Balay }
256