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 /*@C 166 PetscObjectListFind - givn a name, find the matching object 167 168 Input Parameters: 169 + fl - pointer to list 170 - name - name string 171 172 Output Parameters: 173 . obj - the PETSc object 174 175 Level: developer 176 177 Notes: 178 The name must have been registered with the PetscObjectListAdd() before calling this routine. 179 180 The reference count of the object is not increased 181 182 .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate() 183 184 @*/ 185 PetscErrorCode PetscObjectListFind(PetscObjectList fl,const char name[],PetscObject *obj) 186 { 187 PetscErrorCode ierr; 188 PetscBool match; 189 190 PetscFunctionBegin; 191 *obj = NULL; 192 while (fl) { 193 ierr = PetscStrcmp(name,fl->name,&match);CHKERRQ(ierr); 194 if (match) { 195 *obj = fl->obj; 196 break; 197 } 198 fl = fl->next; 199 } 200 PetscFunctionReturn(0); 201 } 202 203 /*@C 204 PetscObjectListReverseFind - given a object, find the matching name if it exists 205 206 Input Parameters: 207 + fl - pointer to list 208 - obj - the PETSc object 209 210 Output Parameters: 211 + name - name string 212 - skipdereference - if the object is in list but does not have the increased reference count for a circular dependency 213 214 Level: developer 215 216 Notes: 217 The name must have been registered with the PetscObjectListAdd() before calling this routine. 218 219 The reference count of the object is not increased 220 221 .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListFind(), PetscObjectListDuplicate() 222 223 @*/ 224 PetscErrorCode PetscObjectListReverseFind(PetscObjectList fl,PetscObject obj,char **name,PetscBool *skipdereference) 225 { 226 PetscFunctionBegin; 227 *name = NULL; 228 while (fl) { 229 if (fl->obj == obj) { 230 *name = fl->name; 231 if (skipdereference) *skipdereference = fl->skipdereference; 232 break; 233 } 234 fl = fl->next; 235 } 236 PetscFunctionReturn(0); 237 } 238 239 /*@C 240 PetscObjectListDuplicate - Creates a new list from a given object list. 241 242 Input Parameters: 243 . fl - pointer to list 244 245 Output Parameters: 246 . nl - the new list (should point to 0 to start, otherwise appends) 247 248 Level: developer 249 250 .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListReverseFind(), PetscObjectListFind(), PetscObjectListDuplicate() 251 252 @*/ 253 PetscErrorCode PetscObjectListDuplicate(PetscObjectList fl,PetscObjectList *nl) 254 { 255 PetscErrorCode ierr; 256 257 PetscFunctionBegin; 258 while (fl) { 259 ierr = PetscObjectListAdd(nl,fl->name,fl->obj);CHKERRQ(ierr); 260 fl = fl->next; 261 } 262 PetscFunctionReturn(0); 263 } 264