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