Goroutines in Fortran
A goroutine is a lightweight thread of execution.
program goroutines
implicit none
call f('direct')
call execute_goroutine('goroutine')
call execute_anonymous('going')
call sleep(1.0)
print *, 'done'
contains
subroutine f(from)
character(len=*), intent(in) :: from
integer :: i
do i = 0, 2
print *, trim(from), ":", i
end do
end subroutine f
subroutine execute_goroutine(from)
character(len=*), intent(in) :: from
call execute_task('f', trim(from))
end subroutine execute_goroutine
subroutine execute_anonymous(msg)
character(len=*), intent(in) :: msg
call execute_task('anonymous', trim(msg))
end subroutine execute_anonymous
subroutine anonymous_task(msg)
character(len=*), intent(in) :: msg
print *, trim(msg)
end subroutine anonymous_task
subroutine execute_task(task, msg)
character(len=*), intent(in) :: task, msg
if (trim(task) == 'f') then
call f(msg)
else if (trim(task) == 'anonymous') then
call anonymous_task(msg)
end if
! For simplicity, simulate async behavior with sleep
call sleep(0.5)
end subroutine execute_task
subroutine sleep(seconds)
real, intent(in) :: seconds
integer :: i, istat
real :: start_time, end_time
call cpu_time(start_time)
end_time = start_time + seconds
do
call cpu_time(start_time)
if (start_time >= end_time) exit
end do
end subroutine sleep
end program goroutines
Suppose we have a subroutine call f(s)
. Here’s how we’d call that in the usual way, running it synchronously.
call f('direct')
To invoke this subroutine in a goroutine-like fashion, we simulate asynchronous behavior by calling it within another subroutine.
call execute_goroutine('goroutine')
You can also start a subroutine for an anonymous function call.
call execute_anonymous('going')
Our two subroutine calls are running asynchronously now. We use a sleep subroutine to wait for them to finish (for a more robust approach, use proper concurrency control).
call sleep(1.0)
print *, 'done'
When we run this program, we see the output of the blocking call first, then the output of the simulated goroutines. The outputs may be interleaved because they are being run concurrently in our simulation.
$ gfortran -o goroutines goroutines.f90
$ ./goroutines
direct : 0
direct : 1
direct : 2
goroutine : 0
going
goroutine : 1
goroutine : 2
done
Next, we’ll look at a complement to goroutines in concurrent programs: channels.