20

Does anyone know of an way to sleep for a given number of milliseconds in Fortran? I do not want to use non-portable system calls so anything intrinsic to Fortran or C libraries would be preferred.

M. S. B.
  • 28,968
  • 2
  • 46
  • 73
Brian Triplett
  • 3,462
  • 6
  • 35
  • 61
  • There is a 'sleep' subroutine that takes a number of seconds as an argument but I'm not sure where that's coming from (wrapper to C function?). It seems to work fine for what I'm intending. I'm using the Intel Fortran Compiler 12 on a PC. – Brian Triplett Aug 03 '11 at 19:36
  • I just ran across a Fortran program that uses a (non-standard) call system(char_arg) that accesses system with no cpu overhead. Tried it out with pgf90, ifort, and gfortran, all are fine with it. So, one could do something like call system('sleep '//number_of_seconds_string) to obtain a sleep function. Did not have a chance to test this with other compilers. – milancurcic Aug 31 '11 at 20:12
  • I think the `sleep` subroutine @BrianTriplett talks is a gnu extension, so I don't know if it fits the being portable requirement – Manuel Pena May 17 '20 at 00:36

3 Answers3

15

Using the Fortran ISO C Binding to use the C library sleep to sleep in units of seconds:

   module Fortran_Sleep

   use, intrinsic :: iso_c_binding, only: c_int

   implicit none

   interface

      !  should be unsigned int ... not available in Fortran
      !  OK until highest bit gets set.
      function FortSleep (seconds)  bind ( C, name="sleep" )
          import
          integer (c_int) :: FortSleep
          integer (c_int), intent (in), VALUE :: seconds
      end function FortSleep

   end interface

end module Fortran_Sleep


program test_Fortran_Sleep

   use, intrinsic :: iso_c_binding, only: c_int

   use Fortran_Sleep

   implicit none

   integer (c_int) :: wait_sec, how_long

   write (*, '( "Input sleep time: " )', advance='no')
   read (*, *) wait_sec
   how_long = FortSleep ( wait_sec )

   write (*, *) how_long

   stop

end program test_Fortran_Sleep
M. S. B.
  • 28,968
  • 2
  • 46
  • 73
  • do you think the 'sleep' function provided inside of Intel Fortran is basically doing the same thing you provided above? – Brian Triplett Aug 03 '11 at 19:47
  • Yes, the functionally is probably the same. A similar subroutine is available in gfortran. This is an extension that might not be part of some other compiler. – M. S. B. Aug 03 '11 at 21:07
  • 1
    Hi, in Linux I could use this and it works fine. In Windows and using MinGW, when compiling it complains that it cannot find Sleep function. Do you know how to fix this? – Hossein Talebi Apr 20 '14 at 14:37
  • This solution is not portable across OSes. (*nix only, I believe.) @milancurcic 's answer below should work across all OSes. – zbeekman Aug 06 '18 at 19:32
4

You can use Fortran standard intrinsic functions to do this without C binding:

program sleep
!===============================================================================
implicit none
character(len=100) :: arg ! input argument character string
integer,dimension(8) :: t ! arguments for date_and_time
integer :: s1,s2,ms1,ms2  ! start and end times [ms]
real :: dt                ! desired sleep interval [ms]
!===============================================================================
! Get start time:
call date_and_time(values=t)
ms1=(t(5)*3600+t(6)*60+t(7))*1000+t(8)

! Get the command argument, e.g. sleep time in milliseconds:
call get_command_argument(number=1,value=arg)
read(unit=arg,fmt=*)dt

do ! check time:
  call date_and_time(values=t)
  ms2=(t(5)*3600+t(6)*60+t(7))*1000+t(8)
  if(ms2-ms1>=dt)exit
enddo
!===============================================================================
endprogram sleep

Assuming the executable is slp:

~$ time slp 1234

real        0m1.237s
user        0m1.233s
sys         0m0.003s 

Add a special case to this program if you are worried it will break around midnight :)

milancurcic
  • 6,202
  • 2
  • 34
  • 47
-1
      ! This is another option of making your fortran code to wait for x seconds
       Integer :: iStart, iNew
       Real*8 :: rWait, rDT
      ! rWait: seconds that you want to wait for; you can also set this as an (IN)
      ! variable if this code goes into a subroutine that is developed to be called 
      ! from any part of the program.
      rWait = 1.d0; rDT = 0.d0
      call system_clock (iStart)
      do while (rDT <= rWait)
          call system_clock (iNew)
          rDT = floatj (iNew - iStart) / 10000.d0
      enddo
George
  • 1
  • 2
    system_clock is still non-portable. It may behave differently on different systems/different compilers. [Check out this answer already.](https://stackoverflow.com/questions/6878246/fortran-intrinsic-timing-routines-which-is-better-cpu-time-or-system-clock) – Dan Sp. Aug 19 '18 at 20:44
  • 1
    It is portable, but one has to query the clock rate and use the value one gets. Also, this is just *busy wating* https://en.wikipedia.org/wiki/Busy_waiting, not proper sleeping. – Vladimir F Героям слава Aug 20 '18 at 07:09