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,prev; 38 PetscErrorCode ierr; 39 PetscBool match; 40 41 PetscFunctionBegin; 42 nlist = *fl; prev = 0; 43 while (nlist) { 44 ierr = PetscStrcmp(name,nlist->name,&match);CHKERRQ(ierr); 45 if (match) { /* found it in the list */ 46 ierr = PetscObjectDereference(nlist->obj);CHKERRQ(ierr); 47 nlist->skipdereference = PETSC_TRUE; 48 PetscFunctionReturn(0); 49 } 50 prev = nlist; 51 nlist = nlist->next; 52 } 53 PetscFunctionReturn(0); 54 } 55 56 #undef __FUNCT__ 57 #define __FUNCT__ "PetscOListAdd" 58 /*@C 59 PetscOListAdd - Adds a new object to an PetscOList 60 61 Input Parameters: 62 + fl - the object list 63 . name - the name to use for the object 64 - obj - the object to attach 65 66 Level: developer 67 68 Notes: Replaces item if it is already in list. Removes item if you pass in a PETSC_NULL object. 69 70 Use PetscOListFind() or PetscOListReverseFind() to get the object back 71 72 .seealso: PetscOListDestroy(), PetscOListFind(), PetscOListDuplicate(), PetscOListReverseFind(), PetscOListDuplicate() 73 74 @*/ 75 PetscErrorCode PetscOListAdd(PetscOList *fl,const char name[],PetscObject obj) 76 { 77 PetscOList olist,nlist,prev; 78 PetscErrorCode ierr; 79 PetscBool match; 80 81 PetscFunctionBegin; 82 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 ierr = PetscObjectDereference(nlist->obj);CHKERRQ(ierr); 89 if (prev) prev->next = nlist->next; 90 else if (nlist->next) { 91 *fl = nlist->next; 92 } else { 93 *fl = 0; 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 ierr = PetscObjectDereference(nlist->obj);CHKERRQ(ierr); 110 nlist->obj = obj; 111 PetscFunctionReturn(0); 112 } 113 nlist = nlist->next; 114 } 115 116 /* add it to list, because it was not already there */ 117 118 ierr = PetscNew(struct _n_PetscOList,&olist);CHKERRQ(ierr); 119 olist->next = 0; 120 olist->obj = obj; 121 ierr = PetscObjectReference(obj);CHKERRQ(ierr); 122 ierr = PetscStrcpy(olist->name,name);CHKERRQ(ierr); 123 124 if (!*fl) { 125 *fl = olist; 126 } else { /* go to end of list */ 127 nlist = *fl; 128 while (nlist->next) { 129 nlist = nlist->next; 130 } 131 nlist->next = olist; 132 } 133 PetscFunctionReturn(0); 134 } 135 136 #undef __FUNCT__ 137 #define __FUNCT__ "PetscOListDestroy" 138 /*@C 139 PetscOListDestroy - Destroy a list of objects 140 141 Input Parameter: 142 . ifl - pointer to list 143 144 Level: developer 145 146 .seealso: PetscOListAdd(), PetscOListFind(), PetscOListDuplicate(), PetscOListReverseFind(), PetscOListDuplicate() 147 148 @*/ 149 PetscErrorCode PetscOListDestroy(PetscOList *ifl) 150 { 151 PetscOList tmp,fl = *ifl; 152 PetscErrorCode ierr; 153 154 PetscFunctionBegin; 155 while (fl) { 156 tmp = fl->next; 157 if (!fl->skipdereference) {ierr = PetscObjectDereference(fl->obj);CHKERRQ(ierr);} 158 ierr = PetscFree(fl);CHKERRQ(ierr); 159 fl = tmp; 160 } 161 *ifl = PETSC_NULL; 162 PetscFunctionReturn(0); 163 } 164 165 166 #undef __FUNCT__ 167 #define __FUNCT__ "PetscOListFind" 168 /*@C 169 PetscOListFind - givn a name, find the matching object 170 171 Input Parameters: 172 + fl - pointer to list 173 - name - name string 174 175 Output Parameters: 176 . ob - the PETSc object 177 178 Level: developer 179 180 Notes: 181 The name must have been registered with the PetscOListAdd() before calling this routine. 182 183 The reference count of the object is not increased 184 185 .seealso: PetscOListDestroy(), PetscOListAdd(), PetscOListDuplicate(), PetscOListReverseFind(), PetscOListDuplicate() 186 187 @*/ 188 PetscErrorCode PetscOListFind(PetscOList fl,const char name[],PetscObject *obj) 189 { 190 PetscErrorCode ierr; 191 PetscBool match; 192 193 PetscFunctionBegin; 194 *obj = 0; 195 while (fl) { 196 ierr = PetscStrcmp(name,fl->name,&match);CHKERRQ(ierr); 197 if (match) { 198 *obj = fl->obj; 199 break; 200 } 201 fl = fl->next; 202 } 203 PetscFunctionReturn(0); 204 } 205 206 #undef __FUNCT__ 207 #define __FUNCT__ "PetscOListReverseFind" 208 /*@C 209 PetscOListReverseFind - given a object, find the matching name if it exists 210 211 Input Parameters: 212 + fl - pointer to list 213 - ob - the PETSc object 214 215 Output Parameters: 216 . name - name string 217 218 Level: developer 219 220 Notes: 221 The name must have been registered with the PetscOListAdd() before calling this routine. 222 223 The reference count of the object is not increased 224 225 .seealso: PetscOListDestroy(), PetscOListAdd(), PetscOListDuplicate(), PetscOListFind(), PetscOListDuplicate() 226 227 @*/ 228 PetscErrorCode PetscOListReverseFind(PetscOList fl,PetscObject obj,char **name) 229 { 230 PetscFunctionBegin; 231 *name = 0; 232 while (fl) { 233 if (fl->obj == obj) { 234 *name = fl->name; 235 break; 236 } 237 fl = fl->next; 238 } 239 PetscFunctionReturn(0); 240 } 241 242 #undef __FUNCT__ 243 #define __FUNCT__ "PetscOListDuplicate" 244 /*@C 245 PetscOListDuplicate - Creates a new list from a give object list. 246 247 Input Parameters: 248 . fl - pointer to list 249 250 Output Parameters: 251 . nl - the new list (should point to 0 to start, otherwise appends) 252 253 Level: developer 254 255 .seealso: PetscOListDestroy(), PetscOListAdd(), PetscOListReverseFind(), PetscOListFind(), PetscOListDuplicate() 256 257 @*/ 258 PetscErrorCode PetscOListDuplicate(PetscOList fl,PetscOList *nl) 259 { 260 PetscErrorCode ierr; 261 262 PetscFunctionBegin; 263 while (fl) { 264 ierr = PetscOListAdd(nl,fl->name,fl->obj);CHKERRQ(ierr); 265 fl = fl->next; 266 } 267 PetscFunctionReturn(0); 268 } 269 270 271 272 273 274