MODULE GROWING_ALLOCATOR_MOD USE ISO_C_BINDING, ONLY: C_INT8_T PRIVATE PUBLIC :: GROWING_ALLOCATION_TYPE PUBLIC :: REALLOCATE_GROWING_ALLOCATION, REGISTER_FREE_FUNCTION ABSTRACT INTERFACE SUBROUTINE FREE_FUNC_PROC(PTR, SZ) BIND(C) USE ISO_C_BINDING, ONLY: C_SIZE_T, C_INT8_T IMPLICIT NONE INTEGER(KIND=C_INT8_T), TARGET :: PTR(:) INTEGER(C_SIZE_T), VALUE :: SZ END SUBROUTINE END INTERFACE TYPE FREE_FUNC_TYPE PROCEDURE(FREE_FUNC_PROC), POINTER, NOPASS :: FUNC => NULL () END TYPE TYPE GROWING_ALLOCATION_TYPE INTEGER(KIND=C_INT8_T), POINTER :: PTR(:) TYPE(FREE_FUNC_TYPE) :: FREE_FUNCS(10) INTEGER :: FREE_FUNCS_SZ END TYPE CONTAINS SUBROUTINE REALLOCATE_GROWING_ALLOCATION(ALLOC, SZ) USE ISO_C_BINDING, ONLY: C_SIZE_T IMPLICIT NONE TYPE(GROWING_ALLOCATION_TYPE), INTENT(INOUT) :: ALLOC INTEGER(C_SIZE_T) :: SZ INTEGER :: I ! Deallocate existing pointer IF (ASSOCIATED(ALLOC%PTR) .AND. SZ > SIZE(ALLOC%PTR, 1, C_SIZE_T)) THEN PRINT *, "WARNING: REALLOCATING GROWING POINTER CAUSING GRAPH REINSTANTIATION" DO I = 1, ALLOC%FREE_FUNCS_SZ CALL ALLOC%FREE_FUNCS(I)%FUNC(ALLOC%PTR, & SIZE(ALLOC%PTR, 1, C_SIZE_T)) ENDDO !$ACC EXIT DATA DELETE(ALLOC%PTR) DEALLOCATE(ALLOC%PTR) NULLIFY(ALLOC%PTR) ENDIF IF (.NOT. ASSOCIATED(ALLOC%PTR)) THEN ALLOCATE(ALLOC%PTR(SZ)) !$ACC ENTER DATA CREATE(ALLOC%PTR) ALLOC%FREE_FUNCS_SZ = 0 ENDIF END SUBROUTINE SUBROUTINE REGISTER_FREE_FUNCTION(ALLOC, FREE_FUNC) IMPLICIT NONE TYPE(GROWING_ALLOCATION_TYPE) :: ALLOC PROCEDURE(FREE_FUNC_PROC) :: FREE_FUNC INTEGER :: I DO I = 1, ALLOC%FREE_FUNCS_SZ IF (ASSOCIATED(ALLOC%FREE_FUNCS(I)%FUNC, FREE_FUNC)) & RETURN ENDDO ALLOC%FREE_FUNCS_SZ = ALLOC%FREE_FUNCS_SZ + 1 IF (ALLOC%FREE_FUNCS_SZ > SIZE(ALLOC%FREE_FUNCS)) THEN PRINT *, "TOO MANY FREE FUNCTIONS REGISTERED" STOP 4 ENDIF ALLOC%FREE_FUNCS(ALLOC%FREE_FUNCS_SZ)%FUNC => FREE_FUNC END SUBROUTINE SUBROUTINE REGISTER_FREE_C(ALLOC_C, FREE_FUNC_C) BIND(C, NAME="growing_allocator_register_free_c") USE ISO_C_BINDING, ONLY: C_FUNPTR, C_PTR, C_F_PROCPOINTER, C_F_POINTER IMPLICIT NONE TYPE(C_PTR), VALUE :: ALLOC_C TYPE(C_FUNPTR), VALUE :: FREE_FUNC_C TYPE(GROWING_ALLOCATION_TYPE), POINTER :: ALLOC PROCEDURE(FREE_FUNC_PROC), POINTER :: FREE_FUNC CALL C_F_POINTER(ALLOC_C, ALLOC) CALL C_F_PROCPOINTER(FREE_FUNC_C, FREE_FUNC) CALL REGISTER_FREE_FUNCTION(ALLOC, FREE_FUNC) END SUBROUTINE END MODULE