xref: /petsc/src/sys/objects/olist.c (revision 4a0791bc0cb6d0c8d66cced23fc19f966b27de4d)
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 */
6c6db04a5SJed Brown #include <petscsys.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 
15e5c89e4eSSatish Balay #undef __FUNCT__
16140e18c1SBarry Smith #define __FUNCT__ "PetscObjectListRemoveReference"
176ba4bc90SBarry Smith /*@C
18140e18c1SBarry Smith      PetscObjectListRemoveReference - Calls PetscObjectDereference() on an object in the list immediately but keeps a pointer to the object in the list.
196ba4bc90SBarry Smith 
206ba4bc90SBarry Smith     Input Parameters:
216ba4bc90SBarry Smith +     fl - the object list
226ba4bc90SBarry Smith -     name - the name to use for the object
236ba4bc90SBarry Smith 
246ba4bc90SBarry Smith     Level: developer
256ba4bc90SBarry Smith 
260298fd71SBarry Smith        Notes: Use PetscObjectListAdd(PetscObjectList,const char name[],NULL) to truly remove the object from the list
276ba4bc90SBarry Smith 
286ba4bc90SBarry Smith               Use this routine ONLY if you know that the object referenced will remain in existence until the pointing object is destroyed
296ba4bc90SBarry Smith 
306ba4bc90SBarry Smith       Developer Note: this is to handle some cases that otherwise would result in having circular references so reference counts never got to zero
316ba4bc90SBarry Smith 
32140e18c1SBarry Smith .seealso: PetscObjectListDestroy(), PetscObjectListFind(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate(), PetscObjectListAdd()
336ba4bc90SBarry Smith 
346ba4bc90SBarry Smith @*/
35140e18c1SBarry Smith PetscErrorCode  PetscObjectListRemoveReference(PetscObjectList *fl,const char name[])
366ba4bc90SBarry Smith {
37140e18c1SBarry Smith   PetscObjectList nlist;
386ba4bc90SBarry Smith   PetscErrorCode  ierr;
396ba4bc90SBarry Smith   PetscBool       match;
406ba4bc90SBarry Smith 
416ba4bc90SBarry Smith   PetscFunctionBegin;
4287130e5eSHong Zhang   nlist = *fl;
436ba4bc90SBarry Smith   while (nlist) {
446ba4bc90SBarry Smith     ierr = PetscStrcmp(name,nlist->name,&match);CHKERRQ(ierr);
4500ac8be1SBarry Smith     if (match) { /* found it in the list */
4600ac8be1SBarry Smith       if (!nlist->skipdereference) {
476ba4bc90SBarry Smith         ierr = PetscObjectDereference(nlist->obj);CHKERRQ(ierr);
4800ac8be1SBarry Smith       }
496ba4bc90SBarry Smith       nlist->skipdereference = PETSC_TRUE;
506ba4bc90SBarry Smith       PetscFunctionReturn(0);
516ba4bc90SBarry Smith     }
526ba4bc90SBarry Smith     nlist = nlist->next;
536ba4bc90SBarry Smith   }
546ba4bc90SBarry Smith   PetscFunctionReturn(0);
556ba4bc90SBarry Smith }
566ba4bc90SBarry Smith 
576ba4bc90SBarry Smith #undef __FUNCT__
58140e18c1SBarry Smith #define __FUNCT__ "PetscObjectListAdd"
591d0fab5eSBarry Smith /*@C
60140e18c1SBarry Smith      PetscObjectListAdd - Adds a new object to an PetscObjectList
61e5c89e4eSSatish Balay 
621d0fab5eSBarry Smith     Input Parameters:
631d0fab5eSBarry Smith +     fl - the object list
641d0fab5eSBarry Smith .     name - the name to use for the object
651d0fab5eSBarry Smith -     obj - the object to attach
66e5c89e4eSSatish Balay 
67b235ab32SBarry Smith     Level: developer
68b235ab32SBarry Smith 
690298fd71SBarry Smith        Notes: Replaces item if it is already in list. Removes item if you pass in a NULL object.
701d0fab5eSBarry Smith 
71140e18c1SBarry Smith         Use PetscObjectListFind() or PetscObjectListReverseFind() to get the object back
721d0fab5eSBarry Smith 
73140e18c1SBarry Smith .seealso: PetscObjectListDestroy(), PetscObjectListFind(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate()
741d0fab5eSBarry Smith 
751d0fab5eSBarry Smith @*/
76140e18c1SBarry Smith PetscErrorCode  PetscObjectListAdd(PetscObjectList *fl,const char name[],PetscObject obj)
77e5c89e4eSSatish Balay {
78140e18c1SBarry Smith   PetscObjectList olist,nlist,prev;
79e5c89e4eSSatish Balay   PetscErrorCode  ierr;
80ace3abfcSBarry Smith   PetscBool       match;
81e5c89e4eSSatish Balay 
82e5c89e4eSSatish Balay   PetscFunctionBegin;
83e5c89e4eSSatish Balay   if (!obj) { /* this means remove from list if it is there */
84e5c89e4eSSatish Balay     nlist = *fl; prev = 0;
85e5c89e4eSSatish Balay     while (nlist) {
86e5c89e4eSSatish Balay       ierr = PetscStrcmp(name,nlist->name,&match);CHKERRQ(ierr);
87e5c89e4eSSatish Balay       if (match) {  /* found it already in the list */
88*4a0791bcSMatthew G. Knepley         /* Remove it first to prevent circular derefs */
89e5c89e4eSSatish Balay         if (prev) prev->next = nlist->next;
90a297a907SKarl Rupp         else if (nlist->next) *fl = nlist->next;
91a297a907SKarl Rupp         else *fl = 0;
92*4a0791bcSMatthew G. Knepley         if (!nlist->skipdereference) {
93*4a0791bcSMatthew G. Knepley           ierr = PetscObjectDereference(nlist->obj);CHKERRQ(ierr);
94*4a0791bcSMatthew G. Knepley         }
95e5c89e4eSSatish Balay         ierr = PetscFree(nlist);CHKERRQ(ierr);
96e5c89e4eSSatish Balay         PetscFunctionReturn(0);
97e5c89e4eSSatish Balay       }
98e5c89e4eSSatish Balay       prev  = nlist;
99e5c89e4eSSatish Balay       nlist = nlist->next;
100e5c89e4eSSatish Balay     }
101e5c89e4eSSatish Balay     PetscFunctionReturn(0); /* did not find it to remove */
102e5c89e4eSSatish Balay   }
103e5c89e4eSSatish Balay   /* look for it already in list */
104e5c89e4eSSatish Balay   nlist = *fl;
105e5c89e4eSSatish Balay   while (nlist) {
106e5c89e4eSSatish Balay     ierr = PetscStrcmp(name,nlist->name,&match);CHKERRQ(ierr);
107e5c89e4eSSatish Balay     if (match) {  /* found it in the list */
108e5c89e4eSSatish Balay       ierr = PetscObjectReference(obj);CHKERRQ(ierr);
10900ac8be1SBarry Smith       if (!nlist->skipdereference) {
1107dcf0eaaSdalcinl         ierr = PetscObjectDereference(nlist->obj);CHKERRQ(ierr);
11100ac8be1SBarry Smith       }
11200ac8be1SBarry Smith       nlist->skipdereference = PETSC_FALSE;
113e5c89e4eSSatish Balay       nlist->obj             = obj;
114e5c89e4eSSatish Balay       PetscFunctionReturn(0);
115e5c89e4eSSatish Balay     }
116e5c89e4eSSatish Balay     nlist = nlist->next;
117e5c89e4eSSatish Balay   }
118e5c89e4eSSatish Balay 
119e5c89e4eSSatish Balay   /* add it to list, because it was not already there */
120140e18c1SBarry Smith   ierr        = PetscNew(struct _n_PetscObjectList,&olist);CHKERRQ(ierr);
121e5c89e4eSSatish Balay   olist->next = 0;
122e5c89e4eSSatish Balay   olist->obj  = obj;
123a297a907SKarl Rupp 
124e5c89e4eSSatish Balay   ierr = PetscObjectReference(obj);CHKERRQ(ierr);
125e5c89e4eSSatish Balay   ierr = PetscStrcpy(olist->name,name);CHKERRQ(ierr);
126e5c89e4eSSatish Balay 
127a297a907SKarl Rupp   if (!*fl) *fl = olist;
128a297a907SKarl Rupp   else { /* go to end of list */
129e5c89e4eSSatish Balay     nlist = *fl;
130e5c89e4eSSatish Balay     while (nlist->next) {
131e5c89e4eSSatish Balay       nlist = nlist->next;
132e5c89e4eSSatish Balay     }
133e5c89e4eSSatish Balay     nlist->next = olist;
134e5c89e4eSSatish Balay   }
135e5c89e4eSSatish Balay   PetscFunctionReturn(0);
136e5c89e4eSSatish Balay }
137e5c89e4eSSatish Balay 
138e5c89e4eSSatish Balay #undef __FUNCT__
139140e18c1SBarry Smith #define __FUNCT__ "PetscObjectListDestroy"
1401d0fab5eSBarry Smith /*@C
141140e18c1SBarry Smith     PetscObjectListDestroy - Destroy a list of objects
142e5c89e4eSSatish Balay 
143e5c89e4eSSatish Balay     Input Parameter:
1446bf464f9SBarry Smith .   ifl   - pointer to list
1451d0fab5eSBarry Smith 
146b235ab32SBarry Smith     Level: developer
147b235ab32SBarry Smith 
148140e18c1SBarry Smith .seealso: PetscObjectListAdd(), PetscObjectListFind(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate()
1491d0fab5eSBarry Smith 
1501d0fab5eSBarry Smith @*/
151140e18c1SBarry Smith PetscErrorCode  PetscObjectListDestroy(PetscObjectList *ifl)
152e5c89e4eSSatish Balay {
153140e18c1SBarry Smith   PetscObjectList tmp,fl = *ifl;
154e5c89e4eSSatish Balay   PetscErrorCode  ierr;
155e5c89e4eSSatish Balay 
156e5c89e4eSSatish Balay   PetscFunctionBegin;
1579c666560SBarry Smith   while (fl) {
1589c666560SBarry Smith     tmp = fl->next;
15900ac8be1SBarry Smith     if (!fl->skipdereference) {
16000ac8be1SBarry Smith       ierr = PetscObjectDereference(fl->obj);CHKERRQ(ierr);
16100ac8be1SBarry Smith     }
1629c666560SBarry Smith     ierr = PetscFree(fl);CHKERRQ(ierr);
1639c666560SBarry Smith     fl   = tmp;
164e5c89e4eSSatish Balay   }
1650298fd71SBarry Smith   *ifl = NULL;
166e5c89e4eSSatish Balay   PetscFunctionReturn(0);
167e5c89e4eSSatish Balay }
168e5c89e4eSSatish Balay 
169e5c89e4eSSatish Balay 
170e5c89e4eSSatish Balay #undef __FUNCT__
171140e18c1SBarry Smith #define __FUNCT__ "PetscObjectListFind"
1721d0fab5eSBarry Smith /*@C
173140e18c1SBarry Smith     PetscObjectListFind - givn a name, find the matching object
174e5c89e4eSSatish Balay 
175e5c89e4eSSatish Balay     Input Parameters:
176e5c89e4eSSatish Balay +   fl   - pointer to list
177e5c89e4eSSatish Balay -   name - name string
178e5c89e4eSSatish Balay 
179e5c89e4eSSatish Balay     Output Parameters:
180e5c89e4eSSatish Balay .   ob - the PETSc object
181e5c89e4eSSatish Balay 
182b235ab32SBarry Smith     Level: developer
183b235ab32SBarry Smith 
184e5c89e4eSSatish Balay     Notes:
185140e18c1SBarry Smith     The name must have been registered with the PetscObjectListAdd() before calling this routine.
1863c0c59f3SBarry Smith 
1873c0c59f3SBarry Smith     The reference count of the object is not increased
188e5c89e4eSSatish Balay 
189140e18c1SBarry Smith .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate()
190e5c89e4eSSatish Balay 
1911d0fab5eSBarry Smith @*/
192140e18c1SBarry Smith PetscErrorCode  PetscObjectListFind(PetscObjectList fl,const char name[],PetscObject *obj)
193e5c89e4eSSatish Balay {
194e5c89e4eSSatish Balay   PetscErrorCode ierr;
195ace3abfcSBarry Smith   PetscBool      match;
196e5c89e4eSSatish Balay 
197e5c89e4eSSatish Balay   PetscFunctionBegin;
198e5c89e4eSSatish Balay   *obj = 0;
199e5c89e4eSSatish Balay   while (fl) {
200e5c89e4eSSatish Balay     ierr = PetscStrcmp(name,fl->name,&match);CHKERRQ(ierr);
201e5c89e4eSSatish Balay     if (match) {
202e5c89e4eSSatish Balay       *obj = fl->obj;
203e5c89e4eSSatish Balay       break;
204e5c89e4eSSatish Balay     }
205e5c89e4eSSatish Balay     fl = fl->next;
206e5c89e4eSSatish Balay   }
207e5c89e4eSSatish Balay   PetscFunctionReturn(0);
208e5c89e4eSSatish Balay }
209e5c89e4eSSatish Balay 
210e5c89e4eSSatish Balay #undef __FUNCT__
211140e18c1SBarry Smith #define __FUNCT__ "PetscObjectListReverseFind"
2121d0fab5eSBarry Smith /*@C
213140e18c1SBarry Smith     PetscObjectListReverseFind - given a object, find the matching name if it exists
214e5c89e4eSSatish Balay 
215e5c89e4eSSatish Balay     Input Parameters:
216e5c89e4eSSatish Balay +   fl   - pointer to list
217e5c89e4eSSatish Balay -   ob - the PETSc object
218e5c89e4eSSatish Balay 
219e5c89e4eSSatish Balay     Output Parameters:
220bfec8eecSBarry Smith +  name - name string
221bfec8eecSBarry Smith -  skipdereference - if the object is list but does not have the increased reference count for a circular dependency
222e5c89e4eSSatish Balay 
223b235ab32SBarry Smith     Level: developer
224b235ab32SBarry Smith 
225e5c89e4eSSatish Balay     Notes:
226140e18c1SBarry Smith     The name must have been registered with the PetscObjectListAdd() before calling this routine.
2273c0c59f3SBarry Smith 
2283c0c59f3SBarry Smith     The reference count of the object is not increased
229e5c89e4eSSatish Balay 
230140e18c1SBarry Smith .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListFind(), PetscObjectListDuplicate()
231e5c89e4eSSatish Balay 
2321d0fab5eSBarry Smith @*/
233140e18c1SBarry Smith PetscErrorCode  PetscObjectListReverseFind(PetscObjectList fl,PetscObject obj,char **name,PetscBool *skipdereference)
234e5c89e4eSSatish Balay {
235e5c89e4eSSatish Balay   PetscFunctionBegin;
236e5c89e4eSSatish Balay   *name = 0;
237e5c89e4eSSatish Balay   while (fl) {
238e5c89e4eSSatish Balay     if (fl->obj == obj) {
239e5c89e4eSSatish Balay       *name = fl->name;
240bfec8eecSBarry Smith       if (skipdereference) *skipdereference = fl->skipdereference;
241e5c89e4eSSatish Balay       break;
242e5c89e4eSSatish Balay     }
243e5c89e4eSSatish Balay     fl = fl->next;
244e5c89e4eSSatish Balay   }
245e5c89e4eSSatish Balay   PetscFunctionReturn(0);
246e5c89e4eSSatish Balay }
247e5c89e4eSSatish Balay 
248e5c89e4eSSatish Balay #undef __FUNCT__
249140e18c1SBarry Smith #define __FUNCT__ "PetscObjectListDuplicate"
2501d0fab5eSBarry Smith /*@C
251140e18c1SBarry Smith     PetscObjectListDuplicate - Creates a new list from a give object list.
252e5c89e4eSSatish Balay 
253e5c89e4eSSatish Balay     Input Parameters:
254e5c89e4eSSatish Balay .   fl   - pointer to list
255e5c89e4eSSatish Balay 
256e5c89e4eSSatish Balay     Output Parameters:
257e5c89e4eSSatish Balay .   nl - the new list (should point to 0 to start, otherwise appends)
258e5c89e4eSSatish Balay 
259b235ab32SBarry Smith     Level: developer
260b235ab32SBarry Smith 
261140e18c1SBarry Smith .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListReverseFind(), PetscObjectListFind(), PetscObjectListDuplicate()
262e5c89e4eSSatish Balay 
2631d0fab5eSBarry Smith @*/
264140e18c1SBarry Smith PetscErrorCode  PetscObjectListDuplicate(PetscObjectList fl,PetscObjectList *nl)
265e5c89e4eSSatish Balay {
266e5c89e4eSSatish Balay   PetscErrorCode ierr;
267e5c89e4eSSatish Balay 
268e5c89e4eSSatish Balay   PetscFunctionBegin;
269e5c89e4eSSatish Balay   while (fl) {
270140e18c1SBarry Smith     ierr = PetscObjectListAdd(nl,fl->name,fl->obj);CHKERRQ(ierr);
271e5c89e4eSSatish Balay     fl   = fl->next;
272e5c89e4eSSatish Balay   }
273e5c89e4eSSatish Balay   PetscFunctionReturn(0);
274e5c89e4eSSatish Balay }
275e5c89e4eSSatish Balay 
276e5c89e4eSSatish Balay 
277e5c89e4eSSatish Balay 
278e5c89e4eSSatish Balay 
279e5c89e4eSSatish Balay 
280