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