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 <petsc/private/petscimpl.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 /*@C 16 PetscObjectListRemoveReference - Calls PetscObjectDereference() on an object in the list immediately but keeps a pointer to the object in the list. 17 18 Input Parameters: 19 + fl - the object list 20 - name - the name to use for the object 21 22 Level: developer 23 24 Notes: 25 Use PetscObjectListAdd(PetscObjectList,const char name[],NULL) to truly remove the object from the list 26 27 Use this routine ONLY if you know that the object referenced will remain in existence until the pointing object is destroyed 28 29 Developer Note: this is to handle some cases that otherwise would result in having circular references so reference counts never got to zero 30 31 .seealso: PetscObjectListDestroy(), PetscObjectListFind(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate(), PetscObjectListAdd() 32 33 @*/ 34 PetscErrorCode PetscObjectListRemoveReference(PetscObjectList *fl,const char name[]) 35 { 36 PetscObjectList nlist; 37 PetscBool match; 38 39 PetscFunctionBegin; 40 PetscValidPointer(fl,1); 41 PetscValidCharPointer(name,2); 42 nlist = *fl; 43 while (nlist) { 44 CHKERRQ(PetscStrcmp(name,nlist->name,&match)); 45 if (match) { /* found it in the list */ 46 if (!nlist->skipdereference) CHKERRQ(PetscObjectDereference(nlist->obj)); 47 nlist->skipdereference = PETSC_TRUE; 48 PetscFunctionReturn(0); 49 } 50 nlist = nlist->next; 51 } 52 PetscFunctionReturn(0); 53 } 54 55 /*@C 56 PetscObjectListAdd - Adds a new object to an PetscObjectList 57 58 Input Parameters: 59 + fl - the object list 60 . name - the name to use for the object 61 - obj - the object to attach 62 63 Level: developer 64 65 Notes: 66 Replaces item if it is already in list. Removes item if you pass in a NULL object. 67 68 Use PetscObjectListFind() or PetscObjectListReverseFind() to get the object back 69 70 .seealso: PetscObjectListDestroy(), PetscObjectListFind(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate() 71 72 @*/ 73 PetscErrorCode PetscObjectListAdd(PetscObjectList *fl,const char name[],PetscObject obj) 74 { 75 PetscObjectList olist,nlist,prev; 76 PetscBool match; 77 78 PetscFunctionBegin; 79 PetscValidPointer(fl,1); 80 if (!obj) { /* this means remove from list if it is there */ 81 nlist = *fl; prev = NULL; 82 while (nlist) { 83 CHKERRQ(PetscStrcmp(name,nlist->name,&match)); 84 if (match) { /* found it already in the list */ 85 /* Remove it first to prevent circular derefs */ 86 if (prev) prev->next = nlist->next; 87 else if (nlist->next) *fl = nlist->next; 88 else *fl = NULL; 89 if (!nlist->skipdereference) CHKERRQ(PetscObjectDereference(nlist->obj)); 90 CHKERRQ(PetscFree(nlist)); 91 PetscFunctionReturn(0); 92 } 93 prev = nlist; 94 nlist = nlist->next; 95 } 96 PetscFunctionReturn(0); /* did not find it to remove */ 97 } 98 /* look for it already in list */ 99 nlist = *fl; 100 while (nlist) { 101 CHKERRQ(PetscStrcmp(name,nlist->name,&match)); 102 if (match) { /* found it in the list */ 103 CHKERRQ(PetscObjectReference(obj)); 104 if (!nlist->skipdereference) CHKERRQ(PetscObjectDereference(nlist->obj)); 105 nlist->skipdereference = PETSC_FALSE; 106 nlist->obj = obj; 107 PetscFunctionReturn(0); 108 } 109 nlist = nlist->next; 110 } 111 112 /* add it to list, because it was not already there */ 113 CHKERRQ(PetscNew(&olist)); 114 olist->next = NULL; 115 olist->obj = obj; 116 117 CHKERRQ(PetscObjectReference(obj)); 118 CHKERRQ(PetscStrcpy(olist->name,name)); 119 120 if (!*fl) *fl = olist; 121 else { /* go to end of list */ 122 nlist = *fl; 123 while (nlist->next) nlist = nlist->next; 124 nlist->next = olist; 125 } 126 PetscFunctionReturn(0); 127 } 128 129 /*@C 130 PetscObjectListDestroy - Destroy a list of objects 131 132 Input Parameter: 133 . ifl - pointer to list 134 135 Level: developer 136 137 .seealso: PetscObjectListAdd(), PetscObjectListFind(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate() 138 139 @*/ 140 PetscErrorCode PetscObjectListDestroy(PetscObjectList *ifl) 141 { 142 PetscObjectList tmp,fl; 143 144 PetscFunctionBegin; 145 PetscValidPointer(ifl,1); 146 fl = *ifl; 147 while (fl) { 148 tmp = fl->next; 149 if (!fl->skipdereference) CHKERRQ(PetscObjectDereference(fl->obj)); 150 CHKERRQ(PetscFree(fl)); 151 fl = tmp; 152 } 153 *ifl = NULL; 154 PetscFunctionReturn(0); 155 } 156 157 /*@C 158 PetscObjectListFind - givn a name, find the matching object 159 160 Input Parameters: 161 + fl - pointer to list 162 - name - name string 163 164 Output Parameters: 165 . obj - the PETSc object 166 167 Level: developer 168 169 Notes: 170 The name must have been registered with the PetscObjectListAdd() before calling this routine. 171 172 The reference count of the object is not increased 173 174 .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListReverseFind(), PetscObjectListDuplicate() 175 176 @*/ 177 PetscErrorCode PetscObjectListFind(PetscObjectList fl,const char name[],PetscObject *obj) 178 { 179 PetscFunctionBegin; 180 PetscValidPointer(obj,3); 181 *obj = NULL; 182 while (fl) { 183 PetscBool match; 184 CHKERRQ(PetscStrcmp(name,fl->name,&match)); 185 if (match) { 186 *obj = fl->obj; 187 break; 188 } 189 fl = fl->next; 190 } 191 PetscFunctionReturn(0); 192 } 193 194 /*@C 195 PetscObjectListReverseFind - given a object, find the matching name if it exists 196 197 Input Parameters: 198 + fl - pointer to list 199 - obj - the PETSc object 200 201 Output Parameters: 202 + name - name string 203 - skipdereference - if the object is in list but does not have the increased reference count for a circular dependency 204 205 Level: developer 206 207 Notes: 208 The name must have been registered with the PetscObjectListAdd() before calling this routine. 209 210 The reference count of the object is not increased 211 212 .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListDuplicate(), PetscObjectListFind(), PetscObjectListDuplicate() 213 214 @*/ 215 PetscErrorCode PetscObjectListReverseFind(PetscObjectList fl,PetscObject obj,char **name,PetscBool *skipdereference) 216 { 217 PetscFunctionBegin; 218 PetscValidPointer(name,3); 219 if (skipdereference) PetscValidBoolPointer(skipdereference,4); 220 *name = NULL; 221 while (fl) { 222 if (fl->obj == obj) { 223 *name = fl->name; 224 if (skipdereference) *skipdereference = fl->skipdereference; 225 break; 226 } 227 fl = fl->next; 228 } 229 PetscFunctionReturn(0); 230 } 231 232 /*@C 233 PetscObjectListDuplicate - Creates a new list from a given object list. 234 235 Input Parameters: 236 . fl - pointer to list 237 238 Output Parameters: 239 . nl - the new list (should point to 0 to start, otherwise appends) 240 241 Level: developer 242 243 .seealso: PetscObjectListDestroy(), PetscObjectListAdd(), PetscObjectListReverseFind(), PetscObjectListFind(), PetscObjectListDuplicate() 244 245 @*/ 246 PetscErrorCode PetscObjectListDuplicate(PetscObjectList fl,PetscObjectList *nl) 247 { 248 PetscFunctionBegin; 249 PetscValidPointer(nl,2); 250 while (fl) { 251 CHKERRQ(PetscObjectListAdd(nl,fl->name,fl->obj)); 252 fl = fl->next; 253 } 254 PetscFunctionReturn(0); 255 } 256