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 if (!obj) { /* this means remove from list if it is there */ 84 nlist = *fl; prev = 0; 85 while (nlist) { 86 ierr = PetscStrcmp(name,nlist->name,&match);CHKERRQ(ierr); 87 if (match) { /* found it already in the list */ 88 if (!nlist->skipdereference) { 89 ierr = PetscObjectDereference(nlist->obj);CHKERRQ(ierr); 90 } 91 if (prev) prev->next = nlist->next; 92 else if (nlist->next) { 93 *fl = nlist->next; 94 } else { 95 *fl = 0; 96 } 97 ierr = PetscFree(nlist);CHKERRQ(ierr); 98 PetscFunctionReturn(0); 99 } 100 prev = nlist; 101 nlist = nlist->next; 102 } 103 PetscFunctionReturn(0); /* did not find it to remove */ 104 } 105 /* look for it already in list */ 106 nlist = *fl; 107 while (nlist) { 108 ierr = PetscStrcmp(name,nlist->name,&match);CHKERRQ(ierr); 109 if (match) { /* found it in the list */ 110 ierr = PetscObjectReference(obj);CHKERRQ(ierr); 111 if (!nlist->skipdereference) { 112 ierr = PetscObjectDereference(nlist->obj);CHKERRQ(ierr); 113 } 114 nlist->skipdereference = PETSC_FALSE; 115 nlist->obj = obj; 116 PetscFunctionReturn(0); 117 } 118 nlist = nlist->next; 119 } 120 121 /* add it to list, because it was not already there */ 122 ierr = PetscNew(struct _n_PetscObjectList,&olist);CHKERRQ(ierr); 123 olist->next = 0; 124 olist->obj = obj; 125 ierr = PetscObjectReference(obj);CHKERRQ(ierr); 126 ierr = PetscStrcpy(olist->name,name);CHKERRQ(ierr); 127 128 if (!*fl) { 129 *fl = olist; 130 } else { /* go to end of list */ 131 nlist = *fl; 132 while (nlist->next) { 133 nlist = nlist->next; 134 } 135 nlist->next = olist; 136 } 137 PetscFunctionReturn(0); 138 } 139 140 #undef __FUNCT__ 141 #define __FUNCT__ "PetscObjectListDestroy" 142 /*@C 143 PetscObjectListDestroy - Destroy a list of objects 144 145 Input Parameter: 146 . ifl - pointer to list 147 148 Level: developer 149 150 .seealso: PetscObjectListAdd(), PetscObjectListFind(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate() 151 152 @*/ 153 PetscErrorCode PetscObjectListDestroy(PetscObjectList *ifl) 154 { 155 PetscObjectList tmp,fl = *ifl; 156 PetscErrorCode ierr; 157 158 PetscFunctionBegin; 159 while (fl) { 160 tmp = fl->next; 161 if (!fl->skipdereference) { 162 ierr = PetscObjectDereference(fl->obj);CHKERRQ(ierr); 163 } 164 ierr = PetscFree(fl);CHKERRQ(ierr); 165 fl = tmp; 166 } 167 *ifl = PETSC_NULL; 168 PetscFunctionReturn(0); 169 } 170 171 172 #undef __FUNCT__ 173 #define __FUNCT__ "PetscObjectListFind" 174 /*@C 175 PetscObjectListFind - givn a name, find the matching object 176 177 Input Parameters: 178 + fl - pointer to list 179 - name - name string 180 181 Output Parameters: 182 . ob - the PETSc object 183 184 Level: developer 185 186 Notes: 187 The name must have been registered with the PetscObjectListAdd() before calling this routine. 188 189 The reference count of the object is not increased 190 191 .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate() 192 193 @*/ 194 PetscErrorCode PetscObjectListFind(PetscObjectList fl,const char name[],PetscObject *obj) 195 { 196 PetscErrorCode ierr; 197 PetscBool match; 198 199 PetscFunctionBegin; 200 *obj = 0; 201 while (fl) { 202 ierr = PetscStrcmp(name,fl->name,&match);CHKERRQ(ierr); 203 if (match) { 204 *obj = fl->obj; 205 break; 206 } 207 fl = fl->next; 208 } 209 PetscFunctionReturn(0); 210 } 211 212 #undef __FUNCT__ 213 #define __FUNCT__ "PetscObjectListReverseFind" 214 /*@C 215 PetscObjectListReverseFind - given a object, find the matching name if it exists 216 217 Input Parameters: 218 + fl - pointer to list 219 - ob - the PETSc object 220 221 Output Parameters: 222 + name - name string 223 - skipdereference - if the object is list but does not have the increased reference count for a circular dependency 224 225 Level: developer 226 227 Notes: 228 The name must have been registered with the PetscObjectListAdd() before calling this routine. 229 230 The reference count of the object is not increased 231 232 .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListFind(), PetscObjectListDuplicate() 233 234 @*/ 235 PetscErrorCode PetscObjectListReverseFind(PetscObjectList fl,PetscObject obj,char **name,PetscBool *skipdereference) 236 { 237 PetscFunctionBegin; 238 *name = 0; 239 while (fl) { 240 if (fl->obj == obj) { 241 *name = fl->name; 242 if (skipdereference) *skipdereference = fl->skipdereference; 243 break; 244 } 245 fl = fl->next; 246 } 247 PetscFunctionReturn(0); 248 } 249 250 #undef __FUNCT__ 251 #define __FUNCT__ "PetscObjectListDuplicate" 252 /*@C 253 PetscObjectListDuplicate - Creates a new list from a give object list. 254 255 Input Parameters: 256 . fl - pointer to list 257 258 Output Parameters: 259 . nl - the new list (should point to 0 to start, otherwise appends) 260 261 Level: developer 262 263 .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListReverseFind(), PetscObjectListFind(), PetscObjectListDuplicate() 264 265 @*/ 266 PetscErrorCode PetscObjectListDuplicate(PetscObjectList fl,PetscObjectList *nl) 267 { 268 PetscErrorCode ierr; 269 270 PetscFunctionBegin; 271 while (fl) { 272 ierr = PetscObjectListAdd(nl,fl->name,fl->obj);CHKERRQ(ierr); 273 fl = fl->next; 274 } 275 PetscFunctionReturn(0); 276 } 277 278 279 280 281 282