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