I’m refactoring some old code with common blocks. The common block has many variables, but the old code treats it as one big block of memory, and will use different sets of variables to deal with this memory. For example,
program main
call sub1()
call sub2()
end program
subroutine sub1()
integer :: a,b,c
common a,b,c
a = 1
b = 2
c = 3
end subroutine
subroutine sub2()
integer :: a,d
common a,d(2)
print*,a
print*,d
end subroutine
This program prints
1
2 3
I want to replace these common blocks by passing in/out a derived type. I want to do this so the code is thread-safe. Below is my current solution
module common_stuff
type, bind(c) :: common_data
integer :: a, b, c
end type
end module
program main
use common_stuff
implicit none
type(common_data) :: dat
interface
subroutine sub1(dat1)
import :: common_data
type(common_data), target, intent(inout) :: dat1
end subroutine
subroutine sub2(dat1)
import :: common_data
type(common_data), target, intent(inout) :: dat1
end subroutine
end interface
call sub1(dat)
call sub2(dat)
end program
subroutine sub1(dat)
use common_stuff
type(common_data), target, intent(inout) :: dat
integer, pointer :: a,b,c
a => dat%a
b => dat%b
c => dat%c
a = 1
b = 2
c = 3
end subroutine
subroutine sub2(dat)
use common_stuff
use iso_c_binding
type(common_data), target, intent(inout) :: dat
type(c_ptr) :: dat_ptr
integer, pointer :: a, d(:)
a => dat%a
dat_ptr = c_loc(dat%b)
call c_f_pointer(dat_ptr, d, [2])
print*,a
print*,d
end subroutine
I worry about the mischief I had to do in sub2
. Here I use iso_c_binding to make a c pointer to a variable in the derived type, then I deference the pointer as if it were an array.
Is what i’m doing here OK? Will it be thread-safe? Is there a better way? Do I have to use bind(c)
in the derived type, to guarantee the order of the memory?
Note, the good thing about this approach is that I don’t have to understand the old code at all. I can add some code at the beginning of each subroutine which emulates a common block.