Nice, elegant idea! let’s try to discuss this a bit deeper cause I’m not super expert in this event-driven coding. If I want to do something similar, with the current logic I’d just do:
if (is_completed(process)) call callback(process%exit_state)
However, we could add it part of the process type as a pointer:
procedure(process_oncomplete), pointer :: callback => null()
And then when the process is completed:
! check completion
[...]
process%complete = .true.
! [...] load stdout, stderr
if (associated(process%callback)) &
call process%callback(process%exit_state,process%stdin,process%stdout,process%stderr)
So I think a good callback interface would be
abstract interface
procedure process_oncomplete(exit_state,stdin,stdout,stderr)
integer, intent(in) :: exit_state
! presence depends on allocation status in process type (<- user request)
character(len=*), optional, intent(in) :: stdin,stdout,stderr
end procedure process_oncomplete
end interface
Another slightly related thing is that we may want to ensure the system is not clogged with dangling processes. Should we have a finalizer?
! Process variable goes out of scope: ensure no dangling process
subroutine process_final(process)
type(process_type), intent(inout) :: process
logical :: success
if (is_running(process)) call kill(process, success)
end subroutine