1 2 /* 3 Provides a general mechanism to maintain a linked list of PETSc objects. 4 This is used to allow PETSc objects to carry a list of "composed" objects 5 */ 6 #include <petscsys.h> 7 8 struct _n_PetscObjectList { 9 char name[256]; 10 PetscBool skipdereference; /* when the PetscObjectList is destroyed do not call PetscObjectDereference() on this object */ 11 PetscObject obj; 12 PetscObjectList next; 13 }; 14 15 /*@C 16 PetscObjectListRemoveReference - Calls PetscObjectDereference() on an object in the list immediately but keeps a pointer to the object in the list. 17 18 Input Parameters: 19 + fl - the object list 20 - name - the name to use for the object 21 22 Level: developer 23 24 Notes: 25 Use PetscObjectListAdd(PetscObjectList,const char name[],NULL) to truly remove the object from the list 26 27 Use this routine ONLY if you know that the object referenced will remain in existence until the pointing object is destroyed 28 29 Developer Note: this is to handle some cases that otherwise would result in having circular references so reference counts never got to zero 30 31 .seealso: PetscObjectListDestroy(), PetscObjectListFind(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate(), PetscObjectListAdd() 32 33 @*/ 34 PetscErrorCode PetscObjectListRemoveReference(PetscObjectList *fl,const char name[]) 35 { 36 PetscObjectList nlist; 37 PetscErrorCode ierr; 38 PetscBool match; 39 40 PetscFunctionBegin; 41 nlist = *fl; 42 while (nlist) { 43 ierr = PetscStrcmp(name,nlist->name,&match);CHKERRQ(ierr); 44 if (match) { /* found it in the list */ 45 if (!nlist->skipdereference) { 46 ierr = PetscObjectDereference(nlist->obj);CHKERRQ(ierr); 47 } 48 nlist->skipdereference = PETSC_TRUE; 49 PetscFunctionReturn(0); 50 } 51 nlist = nlist->next; 52 } 53 PetscFunctionReturn(0); 54 } 55 56 /*@C 57 PetscObjectListAdd - Adds a new object to an PetscObjectList 58 59 Input Parameters: 60 + fl - the object list 61 . name - the name to use for the object 62 - obj - the object to attach 63 64 Level: developer 65 66 Notes: 67 Replaces item if it is already in list. Removes item if you pass in a NULL object. 68 69 Use PetscObjectListFind() or PetscObjectListReverseFind() to get the object back 70 71 .seealso: PetscObjectListDestroy(), PetscObjectListFind(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate() 72 73 @*/ 74 PetscErrorCode PetscObjectListAdd(PetscObjectList *fl,const char name[],PetscObject obj) 75 { 76 PetscObjectList olist,nlist,prev; 77 PetscErrorCode ierr; 78 PetscBool match; 79 80 PetscFunctionBegin; 81 if (!obj) { /* this means remove from list if it is there */ 82 nlist = *fl; prev = NULL; 83 while (nlist) { 84 ierr = PetscStrcmp(name,nlist->name,&match);CHKERRQ(ierr); 85 if (match) { /* found it already in the list */ 86 /* Remove it first to prevent circular derefs */ 87 if (prev) prev->next = nlist->next; 88 else if (nlist->next) *fl = nlist->next; 89 else *fl = NULL; 90 if (!nlist->skipdereference) { 91 ierr = PetscObjectDereference(nlist->obj);CHKERRQ(ierr); 92 } 93 ierr = PetscFree(nlist);CHKERRQ(ierr); 94 PetscFunctionReturn(0); 95 } 96 prev = nlist; 97 nlist = nlist->next; 98 } 99 PetscFunctionReturn(0); /* did not find it to remove */ 100 } 101 /* look for it already in list */ 102 nlist = *fl; 103 while (nlist) { 104 ierr = PetscStrcmp(name,nlist->name,&match);CHKERRQ(ierr); 105 if (match) { /* found it in the list */ 106 ierr = PetscObjectReference(obj);CHKERRQ(ierr); 107 if (!nlist->skipdereference) { 108 ierr = PetscObjectDereference(nlist->obj);CHKERRQ(ierr); 109 } 110 nlist->skipdereference = PETSC_FALSE; 111 nlist->obj = obj; 112 PetscFunctionReturn(0); 113 } 114 nlist = nlist->next; 115 } 116 117 /* add it to list, because it was not already there */ 118 ierr = PetscNew(&olist);CHKERRQ(ierr); 119 olist->next = NULL; 120 olist->obj = obj; 121 122 ierr = PetscObjectReference(obj);CHKERRQ(ierr); 123 ierr = PetscStrcpy(olist->name,name);CHKERRQ(ierr); 124 125 if (!*fl) *fl = olist; 126 else { /* go to end of list */ 127 nlist = *fl; 128 while (nlist->next) { 129 nlist = nlist->next; 130 } 131 nlist->next = olist; 132 } 133 PetscFunctionReturn(0); 134 } 135 136 /*@C 137 PetscObjectListDestroy - Destroy a list of objects 138 139 Input Parameter: 140 . ifl - pointer to list 141 142 Level: developer 143 144 .seealso: PetscObjectListAdd(), PetscObjectListFind(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate() 145 146 @*/ 147 PetscErrorCode PetscObjectListDestroy(PetscObjectList *ifl) 148 { 149 PetscObjectList tmp,fl = *ifl; 150 PetscErrorCode ierr; 151 152 PetscFunctionBegin; 153 while (fl) { 154 tmp = fl->next; 155 if (!fl->skipdereference) { 156 ierr = PetscObjectDereference(fl->obj);CHKERRQ(ierr); 157 } 158 ierr = PetscFree(fl);CHKERRQ(ierr); 159 fl = tmp; 160 } 161 *ifl = NULL; 162 PetscFunctionReturn(0); 163 } 164 165 166 /*@C 167 PetscObjectListFind - givn a name, find the matching object 168 169 Input Parameters: 170 + fl - pointer to list 171 - name - name string 172 173 Output Parameters: 174 . obj - the PETSc object 175 176 Level: developer 177 178 Notes: 179 The name must have been registered with the PetscObjectListAdd() before calling this routine. 180 181 The reference count of the object is not increased 182 183 .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate() 184 185 @*/ 186 PetscErrorCode PetscObjectListFind(PetscObjectList fl,const char name[],PetscObject *obj) 187 { 188 PetscErrorCode ierr; 189 PetscBool match; 190 191 PetscFunctionBegin; 192 *obj = NULL; 193 while (fl) { 194 ierr = PetscStrcmp(name,fl->name,&match);CHKERRQ(ierr); 195 if (match) { 196 *obj = fl->obj; 197 break; 198 } 199 fl = fl->next; 200 } 201 PetscFunctionReturn(0); 202 } 203 204 /*@C 205 PetscObjectListReverseFind - given a object, find the matching name if it exists 206 207 Input Parameters: 208 + fl - pointer to list 209 - obj - the PETSc object 210 211 Output Parameters: 212 + name - name string 213 - skipdereference - if the object is in list but does not have the increased reference count for a circular dependency 214 215 Level: developer 216 217 Notes: 218 The name must have been registered with the PetscObjectListAdd() before calling this routine. 219 220 The reference count of the object is not increased 221 222 .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListFind(), PetscObjectListDuplicate() 223 224 @*/ 225 PetscErrorCode PetscObjectListReverseFind(PetscObjectList fl,PetscObject obj,char **name,PetscBool *skipdereference) 226 { 227 PetscFunctionBegin; 228 *name = NULL; 229 while (fl) { 230 if (fl->obj == obj) { 231 *name = fl->name; 232 if (skipdereference) *skipdereference = fl->skipdereference; 233 break; 234 } 235 fl = fl->next; 236 } 237 PetscFunctionReturn(0); 238 } 239 240 /*@C 241 PetscObjectListDuplicate - Creates a new list from a given object list. 242 243 Input Parameters: 244 . fl - pointer to list 245 246 Output Parameters: 247 . nl - the new list (should point to 0 to start, otherwise appends) 248 249 Level: developer 250 251 .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListReverseFind(), PetscObjectListFind(), PetscObjectListDuplicate() 252 253 @*/ 254 PetscErrorCode PetscObjectListDuplicate(PetscObjectList fl,PetscObjectList *nl) 255 { 256 PetscErrorCode ierr; 257 258 PetscFunctionBegin; 259 while (fl) { 260 ierr = PetscObjectListAdd(nl,fl->name,fl->obj);CHKERRQ(ierr); 261 fl = fl->next; 262 } 263 PetscFunctionReturn(0); 264 } 265