Actual source code: fcallback.c
1: #include <petsc/private/petscimpl.h>
3: typedef struct _FortranCallbackLink *FortranCallbackLink;
4: struct _FortranCallbackLink {
5: char *type_name;
6: PetscFortranCallbackId max;
7: FortranCallbackLink next;
8: };
10: typedef struct {
11: PetscFortranCallbackId basecount;
12: PetscFortranCallbackId maxsubtypecount;
13: FortranCallbackLink subtypes;
14: } FortranCallbackBase;
16: static FortranCallbackBase *_classbase;
17: static PetscClassId _maxclassid = PETSC_SMALLEST_CLASSID;
19: static PetscErrorCode PetscFortranCallbackFinalize(void)
20: {
21: PetscFunctionBegin;
22: for (PetscInt i = PETSC_SMALLEST_CLASSID; i < _maxclassid; i++) {
23: FortranCallbackBase *base = &_classbase[i - PETSC_SMALLEST_CLASSID];
24: FortranCallbackLink next, link = base->subtypes;
25: for (; link; link = next) {
26: next = link->next;
27: PetscCall(PetscFree(link->type_name));
28: PetscCall(PetscFree(link));
29: }
30: }
31: PetscCall(PetscFree(_classbase));
32: _maxclassid = PETSC_SMALLEST_CLASSID;
33: PetscFunctionReturn(PETSC_SUCCESS);
34: }
36: /*@C
37: PetscFortranCallbackRegister - register a type+subtype callback. This is used by the PETSc Fortran stubs to allow the use of user Fortran functions
38: as arguments to PETSc functions that take function pointers
40: Not Collective
42: Input Parameters:
43: + classid - ID of class on which to register callback
44: - subtype - subtype string, or `NULL` for class ids
46: Output Parameter:
47: . id - callback id
49: Level: developer
51: .seealso: `PetscFortranCallbackGetSizes()`, `PetscObjectCopyFortranFunctionPointers()`, `PetscObjectSetFortranCallback()`, `PetscObjectGetFortranCallback()`
52: @*/
53: PetscErrorCode PetscFortranCallbackRegister(PetscClassId classid, const char *subtype, PetscFortranCallbackId *id)
54: {
55: FortranCallbackBase *base;
56: FortranCallbackLink link;
58: PetscFunctionBegin;
59: if (subtype) PetscAssertPointer(subtype, 2);
60: PetscAssertPointer(id, 3);
61: PetscCheck(classid >= PETSC_SMALLEST_CLASSID && classid <= PETSC_LARGEST_CLASSID, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "ClassId %d corrupt", classid);
62: *id = 0;
63: if (classid >= _maxclassid) {
64: PetscClassId newmax = PETSC_SMALLEST_CLASSID + 2 * (PETSC_LARGEST_CLASSID - PETSC_SMALLEST_CLASSID);
65: FortranCallbackBase *newbase;
66: if (!_classbase) PetscCall(PetscRegisterFinalize(PetscFortranCallbackFinalize));
67: PetscCall(PetscCalloc1(newmax - PETSC_SMALLEST_CLASSID, &newbase));
68: PetscCall(PetscArraycpy(newbase, _classbase, _maxclassid - PETSC_SMALLEST_CLASSID));
69: PetscCall(PetscFree(_classbase));
71: _classbase = newbase;
72: _maxclassid = newmax;
73: }
74: base = &_classbase[classid - PETSC_SMALLEST_CLASSID];
75: if (!subtype) *id = PETSC_SMALLEST_FORTRAN_CALLBACK + base->basecount++;
76: else {
77: for (link = base->subtypes; link; link = link->next) { /* look for either both NULL or matching values (implies both non-NULL) */
78: PetscBool match;
79: PetscCall(PetscStrcmp(subtype, link->type_name, &match));
80: if (match) { /* base type or matching subtype */
81: goto found;
82: }
83: }
84: /* Not found. Create node and prepend to class' subtype list */
85: PetscCall(PetscNew(&link));
86: PetscCall(PetscStrallocpy(subtype, &link->type_name));
88: link->max = PETSC_SMALLEST_FORTRAN_CALLBACK;
89: link->next = base->subtypes;
90: base->subtypes = link;
92: found:
93: *id = link->max++;
95: base->maxsubtypecount = PetscMax(base->maxsubtypecount, link->max - PETSC_SMALLEST_FORTRAN_CALLBACK);
96: }
97: PetscFunctionReturn(PETSC_SUCCESS);
98: }
100: /*@C
101: PetscFortranCallbackGetSizes - get sizes of class and subtype pointer arrays
103: Collective
105: Input Parameter:
106: . classid - class Id
108: Output Parameters:
109: + numbase - number of registered class callbacks
110: - numsubtype - max number of registered subtype callbacks
112: Level: developer
114: .seealso: `PetscFortranCallbackRegister()`, `PetscObjectCopyFortranFunctionPointers()`, `PetscObjectSetFortranCallback()`, `PetscObjectGetFortranCallback()`
115: @*/
116: PetscErrorCode PetscFortranCallbackGetSizes(PetscClassId classid, PetscFortranCallbackId *numbase, PetscFortranCallbackId *numsubtype)
117: {
118: PetscFunctionBegin;
119: PetscAssertPointer(numbase, 2);
120: PetscAssertPointer(numsubtype, 3);
121: if (classid < _maxclassid) {
122: FortranCallbackBase *base = &_classbase[classid - PETSC_SMALLEST_CLASSID];
123: *numbase = base->basecount;
124: *numsubtype = base->maxsubtypecount;
125: } else { /* nothing registered */
126: *numbase = 0;
127: *numsubtype = 0;
128: }
129: PetscFunctionReturn(PETSC_SUCCESS);
130: }