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