xref: /petsc/src/sys/objects/olist.c (revision 95452b02e12c0ee11232c7ff2b24b568a8e07e43)
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 
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 
24*95452b02SPatrick Sanan        Notes:
25*95452b02SPatrick 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   PetscErrorCode  ierr;
386ba4bc90SBarry Smith   PetscBool       match;
396ba4bc90SBarry Smith 
406ba4bc90SBarry Smith   PetscFunctionBegin;
4187130e5eSHong Zhang   nlist = *fl;
426ba4bc90SBarry Smith   while (nlist) {
436ba4bc90SBarry Smith     ierr = PetscStrcmp(name,nlist->name,&match);CHKERRQ(ierr);
4400ac8be1SBarry Smith     if (match) { /* found it in the list */
4500ac8be1SBarry Smith       if (!nlist->skipdereference) {
466ba4bc90SBarry Smith         ierr = PetscObjectDereference(nlist->obj);CHKERRQ(ierr);
4700ac8be1SBarry Smith       }
486ba4bc90SBarry Smith       nlist->skipdereference = PETSC_TRUE;
496ba4bc90SBarry Smith       PetscFunctionReturn(0);
506ba4bc90SBarry Smith     }
516ba4bc90SBarry Smith     nlist = nlist->next;
526ba4bc90SBarry Smith   }
536ba4bc90SBarry Smith   PetscFunctionReturn(0);
546ba4bc90SBarry Smith }
556ba4bc90SBarry Smith 
561d0fab5eSBarry Smith /*@C
57140e18c1SBarry 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 
66*95452b02SPatrick Sanan        Notes:
67*95452b02SPatrick Sanan     Replaces item if it is already in list. Removes item if you pass in a NULL object.
681d0fab5eSBarry Smith 
69140e18c1SBarry Smith         Use PetscObjectListFind() or PetscObjectListReverseFind() to get the object back
701d0fab5eSBarry Smith 
71140e18c1SBarry Smith .seealso: PetscObjectListDestroy(), PetscObjectListFind(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate()
721d0fab5eSBarry Smith 
731d0fab5eSBarry Smith @*/
74140e18c1SBarry Smith PetscErrorCode  PetscObjectListAdd(PetscObjectList *fl,const char name[],PetscObject obj)
75e5c89e4eSSatish Balay {
76140e18c1SBarry Smith   PetscObjectList olist,nlist,prev;
77e5c89e4eSSatish Balay   PetscErrorCode  ierr;
78ace3abfcSBarry Smith   PetscBool       match;
79e5c89e4eSSatish Balay 
80e5c89e4eSSatish Balay   PetscFunctionBegin;
81e5c89e4eSSatish Balay   if (!obj) { /* this means remove from list if it is there */
82e5c89e4eSSatish Balay     nlist = *fl; prev = 0;
83e5c89e4eSSatish Balay     while (nlist) {
84e5c89e4eSSatish Balay       ierr = PetscStrcmp(name,nlist->name,&match);CHKERRQ(ierr);
85e5c89e4eSSatish Balay       if (match) {  /* found it already in the list */
864a0791bcSMatthew G. Knepley         /* Remove it first to prevent circular derefs */
87e5c89e4eSSatish Balay         if (prev) prev->next = nlist->next;
88a297a907SKarl Rupp         else if (nlist->next) *fl = nlist->next;
89a297a907SKarl Rupp         else *fl = 0;
904a0791bcSMatthew G. Knepley         if (!nlist->skipdereference) {
914a0791bcSMatthew G. Knepley           ierr = PetscObjectDereference(nlist->obj);CHKERRQ(ierr);
924a0791bcSMatthew G. Knepley         }
93e5c89e4eSSatish Balay         ierr = PetscFree(nlist);CHKERRQ(ierr);
94e5c89e4eSSatish Balay         PetscFunctionReturn(0);
95e5c89e4eSSatish Balay       }
96e5c89e4eSSatish Balay       prev  = nlist;
97e5c89e4eSSatish Balay       nlist = nlist->next;
98e5c89e4eSSatish Balay     }
99e5c89e4eSSatish Balay     PetscFunctionReturn(0); /* did not find it to remove */
100e5c89e4eSSatish Balay   }
101e5c89e4eSSatish Balay   /* look for it already in list */
102e5c89e4eSSatish Balay   nlist = *fl;
103e5c89e4eSSatish Balay   while (nlist) {
104e5c89e4eSSatish Balay     ierr = PetscStrcmp(name,nlist->name,&match);CHKERRQ(ierr);
105e5c89e4eSSatish Balay     if (match) {  /* found it in the list */
106e5c89e4eSSatish Balay       ierr = PetscObjectReference(obj);CHKERRQ(ierr);
10700ac8be1SBarry Smith       if (!nlist->skipdereference) {
1087dcf0eaaSdalcinl         ierr = PetscObjectDereference(nlist->obj);CHKERRQ(ierr);
10900ac8be1SBarry Smith       }
11000ac8be1SBarry Smith       nlist->skipdereference = PETSC_FALSE;
111e5c89e4eSSatish Balay       nlist->obj             = obj;
112e5c89e4eSSatish Balay       PetscFunctionReturn(0);
113e5c89e4eSSatish Balay     }
114e5c89e4eSSatish Balay     nlist = nlist->next;
115e5c89e4eSSatish Balay   }
116e5c89e4eSSatish Balay 
117e5c89e4eSSatish Balay   /* add it to list, because it was not already there */
118b00a9115SJed Brown   ierr        = PetscNew(&olist);CHKERRQ(ierr);
119e5c89e4eSSatish Balay   olist->next = 0;
120e5c89e4eSSatish Balay   olist->obj  = obj;
121a297a907SKarl Rupp 
122e5c89e4eSSatish Balay   ierr = PetscObjectReference(obj);CHKERRQ(ierr);
123e5c89e4eSSatish Balay   ierr = PetscStrcpy(olist->name,name);CHKERRQ(ierr);
124e5c89e4eSSatish Balay 
125a297a907SKarl Rupp   if (!*fl) *fl = olist;
126a297a907SKarl Rupp   else { /* go to end of list */
127e5c89e4eSSatish Balay     nlist = *fl;
128e5c89e4eSSatish Balay     while (nlist->next) {
129e5c89e4eSSatish Balay       nlist = nlist->next;
130e5c89e4eSSatish Balay     }
131e5c89e4eSSatish Balay     nlist->next = olist;
132e5c89e4eSSatish Balay   }
133e5c89e4eSSatish Balay   PetscFunctionReturn(0);
134e5c89e4eSSatish Balay }
135e5c89e4eSSatish Balay 
1361d0fab5eSBarry Smith /*@C
137140e18c1SBarry Smith     PetscObjectListDestroy - Destroy a list of objects
138e5c89e4eSSatish Balay 
139e5c89e4eSSatish Balay     Input Parameter:
1406bf464f9SBarry Smith .   ifl   - pointer to list
1411d0fab5eSBarry Smith 
142b235ab32SBarry Smith     Level: developer
143b235ab32SBarry Smith 
144140e18c1SBarry Smith .seealso: PetscObjectListAdd(), PetscObjectListFind(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate()
1451d0fab5eSBarry Smith 
1461d0fab5eSBarry Smith @*/
147140e18c1SBarry Smith PetscErrorCode  PetscObjectListDestroy(PetscObjectList *ifl)
148e5c89e4eSSatish Balay {
149140e18c1SBarry Smith   PetscObjectList tmp,fl = *ifl;
150e5c89e4eSSatish Balay   PetscErrorCode  ierr;
151e5c89e4eSSatish Balay 
152e5c89e4eSSatish Balay   PetscFunctionBegin;
1539c666560SBarry Smith   while (fl) {
1549c666560SBarry Smith     tmp = fl->next;
15500ac8be1SBarry Smith     if (!fl->skipdereference) {
15600ac8be1SBarry Smith       ierr = PetscObjectDereference(fl->obj);CHKERRQ(ierr);
15700ac8be1SBarry Smith     }
1589c666560SBarry Smith     ierr = PetscFree(fl);CHKERRQ(ierr);
1599c666560SBarry Smith     fl   = tmp;
160e5c89e4eSSatish Balay   }
1610298fd71SBarry Smith   *ifl = NULL;
162e5c89e4eSSatish Balay   PetscFunctionReturn(0);
163e5c89e4eSSatish Balay }
164e5c89e4eSSatish Balay 
165e5c89e4eSSatish Balay 
1661d0fab5eSBarry Smith /*@C
167140e18c1SBarry Smith     PetscObjectListFind - givn a name, find the matching object
168e5c89e4eSSatish Balay 
169e5c89e4eSSatish Balay     Input Parameters:
170e5c89e4eSSatish Balay +   fl   - pointer to list
171e5c89e4eSSatish Balay -   name - name string
172e5c89e4eSSatish Balay 
173e5c89e4eSSatish Balay     Output Parameters:
174e5c89e4eSSatish Balay .   ob - the PETSc object
175e5c89e4eSSatish Balay 
176b235ab32SBarry Smith     Level: developer
177b235ab32SBarry Smith 
178e5c89e4eSSatish Balay     Notes:
179140e18c1SBarry Smith     The name must have been registered with the PetscObjectListAdd() before calling this routine.
1803c0c59f3SBarry Smith 
1813c0c59f3SBarry Smith     The reference count of the object is not increased
182e5c89e4eSSatish Balay 
183140e18c1SBarry Smith .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate()
184e5c89e4eSSatish Balay 
1851d0fab5eSBarry Smith @*/
186140e18c1SBarry Smith PetscErrorCode  PetscObjectListFind(PetscObjectList fl,const char name[],PetscObject *obj)
187e5c89e4eSSatish Balay {
188e5c89e4eSSatish Balay   PetscErrorCode ierr;
189ace3abfcSBarry Smith   PetscBool      match;
190e5c89e4eSSatish Balay 
191e5c89e4eSSatish Balay   PetscFunctionBegin;
192e5c89e4eSSatish Balay   *obj = 0;
193e5c89e4eSSatish Balay   while (fl) {
194e5c89e4eSSatish Balay     ierr = PetscStrcmp(name,fl->name,&match);CHKERRQ(ierr);
195e5c89e4eSSatish Balay     if (match) {
196e5c89e4eSSatish Balay       *obj = fl->obj;
197e5c89e4eSSatish Balay       break;
198e5c89e4eSSatish Balay     }
199e5c89e4eSSatish Balay     fl = fl->next;
200e5c89e4eSSatish Balay   }
201e5c89e4eSSatish Balay   PetscFunctionReturn(0);
202e5c89e4eSSatish Balay }
203e5c89e4eSSatish Balay 
2041d0fab5eSBarry Smith /*@C
205140e18c1SBarry Smith     PetscObjectListReverseFind - given a object, find the matching name if it exists
206e5c89e4eSSatish Balay 
207e5c89e4eSSatish Balay     Input Parameters:
208e5c89e4eSSatish Balay +   fl   - pointer to list
209e5c89e4eSSatish Balay -   ob - the PETSc object
210e5c89e4eSSatish Balay 
211e5c89e4eSSatish Balay     Output Parameters:
212bfec8eecSBarry Smith +  name - name string
213bfec8eecSBarry Smith -  skipdereference - if the object is list but does not have the increased reference count for a circular dependency
214e5c89e4eSSatish Balay 
215b235ab32SBarry Smith     Level: developer
216b235ab32SBarry Smith 
217e5c89e4eSSatish Balay     Notes:
218140e18c1SBarry Smith     The name must have been registered with the PetscObjectListAdd() before calling this routine.
2193c0c59f3SBarry Smith 
2203c0c59f3SBarry Smith     The reference count of the object is not increased
221e5c89e4eSSatish Balay 
222140e18c1SBarry Smith .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListFind(), PetscObjectListDuplicate()
223e5c89e4eSSatish Balay 
2241d0fab5eSBarry Smith @*/
225140e18c1SBarry Smith PetscErrorCode  PetscObjectListReverseFind(PetscObjectList fl,PetscObject obj,char **name,PetscBool *skipdereference)
226e5c89e4eSSatish Balay {
227e5c89e4eSSatish Balay   PetscFunctionBegin;
228e5c89e4eSSatish Balay   *name = 0;
229e5c89e4eSSatish Balay   while (fl) {
230e5c89e4eSSatish Balay     if (fl->obj == obj) {
231e5c89e4eSSatish Balay       *name = fl->name;
232bfec8eecSBarry Smith       if (skipdereference) *skipdereference = fl->skipdereference;
233e5c89e4eSSatish Balay       break;
234e5c89e4eSSatish Balay     }
235e5c89e4eSSatish Balay     fl = fl->next;
236e5c89e4eSSatish Balay   }
237e5c89e4eSSatish Balay   PetscFunctionReturn(0);
238e5c89e4eSSatish Balay }
239e5c89e4eSSatish Balay 
2401d0fab5eSBarry Smith /*@C
241140e18c1SBarry Smith     PetscObjectListDuplicate - Creates a new list from a give object list.
242e5c89e4eSSatish Balay 
243e5c89e4eSSatish Balay     Input Parameters:
244e5c89e4eSSatish Balay .   fl   - pointer to list
245e5c89e4eSSatish Balay 
246e5c89e4eSSatish Balay     Output Parameters:
247e5c89e4eSSatish Balay .   nl - the new list (should point to 0 to start, otherwise appends)
248e5c89e4eSSatish Balay 
249b235ab32SBarry Smith     Level: developer
250b235ab32SBarry Smith 
251140e18c1SBarry Smith .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListReverseFind(), PetscObjectListFind(), PetscObjectListDuplicate()
252e5c89e4eSSatish Balay 
2531d0fab5eSBarry Smith @*/
254140e18c1SBarry Smith PetscErrorCode  PetscObjectListDuplicate(PetscObjectList fl,PetscObjectList *nl)
255e5c89e4eSSatish Balay {
256e5c89e4eSSatish Balay   PetscErrorCode ierr;
257e5c89e4eSSatish Balay 
258e5c89e4eSSatish Balay   PetscFunctionBegin;
259e5c89e4eSSatish Balay   while (fl) {
260140e18c1SBarry Smith     ierr = PetscObjectListAdd(nl,fl->name,fl->obj);CHKERRQ(ierr);
261e5c89e4eSSatish Balay     fl   = fl->next;
262e5c89e4eSSatish Balay   }
263e5c89e4eSSatish Balay   PetscFunctionReturn(0);
264e5c89e4eSSatish Balay }
265e5c89e4eSSatish Balay 
266e5c89e4eSSatish Balay 
267e5c89e4eSSatish Balay 
268e5c89e4eSSatish Balay 
269e5c89e4eSSatish Balay 
270