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_PetscOList { 9 char name[256]; 10 PetscBool skipdereference; /* when the OList is destroyed do not call PetscObjectDereference() on this object */ 11 PetscObject obj; 12 PetscOList next; 13 }; 14 15 #undef __FUNCT__ 16 #define __FUNCT__ "PetscOListRemoveReference" 17 /*@C 18 PetscOListRemoveReference - 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 PetscOListAdd(PetscOList,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: PetscOListDestroy(), PetscOListFind(), PetscOListDuplicate(), PetscOListReverseFind(), PetscOListDuplicate(), PetscOListAdd() 33 34 @*/ 35 PetscErrorCode PetscOListRemoveReference(PetscOList *fl,const char name[]) 36 { 37 PetscOList 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__ "PetscOListAdd" 59 /*@C 60 PetscOListAdd - Adds a new object to an PetscOList 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 PetscOListFind() or PetscOListReverseFind() to get the object back 72 73 .seealso: PetscOListDestroy(), PetscOListFind(), PetscOListDuplicate(), PetscOListReverseFind(), PetscOListDuplicate() 74 75 @*/ 76 PetscErrorCode PetscOListAdd(PetscOList *fl,const char name[],PetscObject obj) 77 { 78 PetscOList 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_PetscOList,&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__ "PetscOListDestroy" 143 /*@C 144 PetscOListDestroy - Destroy a list of objects 145 146 Input Parameter: 147 . ifl - pointer to list 148 149 Level: developer 150 151 .seealso: PetscOListAdd(), PetscOListFind(), PetscOListDuplicate(), PetscOListReverseFind(), PetscOListDuplicate() 152 153 @*/ 154 PetscErrorCode PetscOListDestroy(PetscOList *ifl) 155 { 156 PetscOList 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__ "PetscOListFind" 175 /*@C 176 PetscOListFind - 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 PetscOListAdd() before calling this routine. 189 190 The reference count of the object is not increased 191 192 .seealso: PetscOListDestroy(), PetscOListAdd(), PetscOListDuplicate(), PetscOListReverseFind(), PetscOListDuplicate() 193 194 @*/ 195 PetscErrorCode PetscOListFind(PetscOList 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__ "PetscOListReverseFind" 215 /*@C 216 PetscOListReverseFind - 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 PetscOListAdd() before calling this routine. 230 231 The reference count of the object is not increased 232 233 .seealso: PetscOListDestroy(), PetscOListAdd(), PetscOListDuplicate(), PetscOListFind(), PetscOListDuplicate() 234 235 @*/ 236 PetscErrorCode PetscOListReverseFind(PetscOList 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__ "PetscOListDuplicate" 253 /*@C 254 PetscOListDuplicate - 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: PetscOListDestroy(), PetscOListAdd(), PetscOListReverseFind(), PetscOListFind(), PetscOListDuplicate() 265 266 @*/ 267 PetscErrorCode PetscOListDuplicate(PetscOList fl,PetscOList *nl) 268 { 269 PetscErrorCode ierr; 270 271 PetscFunctionBegin; 272 while (fl) { 273 ierr = PetscOListAdd(nl,fl->name,fl->obj);CHKERRQ(ierr); 274 fl = fl->next; 275 } 276 PetscFunctionReturn(0); 277 } 278 279 280 281 282 283