Free an ocean handle. Idempotent on null/already-destroyed/garbage
handles — silently no-ops rather than aborting, so a Python
__del__ can call this blind. Caller is responsible for having
already unwound device residency and called engine_teardown
(engine%state%destroy() releases the god-state’s Fortran
allocations) — h%state is only a pointer VIEW onto
h%engine%state (see ocean_handle_t’s docstring), never
separately allocated, so there is nothing to deallocate through
it here; this only releases the handle’s own heap block
(which takes engine — a value component — down with it).
garbage or already destroyed
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(c_ptr), | intent(inout) | :: | c_handle |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| type(ocean_handle_t), | private, | pointer | :: | h |
subroutine handle_destroy(c_handle) !! Free an ocean handle. Idempotent on null/already-destroyed/garbage !! handles — silently no-ops rather than aborting, so a Python !! `__del__` can call this blind. Caller is responsible for having !! already unwound device residency and called `engine_teardown` !! (`engine%state%destroy()` releases the god-state's Fortran !! allocations) — `h%state` is only a pointer VIEW onto !! `h%engine%state` (see `ocean_handle_t`'s docstring), never !! separately allocated, so there is nothing to deallocate through !! it here; this only releases the handle's own heap block !! (which takes `engine` — a value component — down with it). type(c_ptr), intent(inout) :: c_handle type(ocean_handle_t), pointer :: h if (.not. c_associated(c_handle)) return call c_f_pointer(c_handle, h) if (h%magic /= MAGIC_OCEAN) return !! garbage or already destroyed h%magic = MAGIC_DESTROYED h%state => null() deallocate (h) c_handle = c_null_ptr end subroutine handle_destroy