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