<ATOMIC_XOR Example Program>

Module taskmanager
  Use iso_fortran_env
  Integer(atomic_int_kind) :: ntasks[*] = 2
  Integer,Parameter :: maxtasks = 30
  ! This only works for ntasks up to Bit_Size(0_atomic_int_kind)-1.
  Integer(atomic_int_kind) :: imask[*] = 0
Contains
  Subroutine task_finished(tasknum)
    Integer,Intent(In) :: tasknum
    CALL atomic_xor(imask[1],2**(tasknum-1))
  End Subroutine
  Logical Function task_available(tasknum)
    Integer,Intent(In) :: tasknum
    Integer check,n
    Call atomic_ref(n,ntasks[1])
    If (tasknum>n) Then
      task_available = .False.
    Else
      Call atomic_ref(check,imask[1])
      task_available = .Not.Btest(check,tasknum-1)
    End If
  End Function
  Subroutine newtask
    Integer m
    Call atomic_ref(m,ntasks[1])
    If (m<maxtasks) Call atomic_define(ntasks[1],m+1)
  End Subroutine
  Logical Function all_finished()
    Integer(atomic_int_kind) res,n
    Call atomic_ref(res,imask[1])
    Call atomic_ref(n,ntasks[1])
    all_finished = res==Maskr(n)
  End Function
End Module
Program atomic_xor_example
  Use taskmanager
  Logical :: finished
  Integer mytask
  ! All images will execute until all are finished.
  mytask = This_Image()
  Do
    If (task_available(mytask)) Then
      Call do_task(mytask,finished)
      If (finished) Then
        Call task_finished(mytask)
        mytask = mytask + Num_Images()
      End If
    Else
      If (all_finished()) Exit
      Sync Memory ! Not needed, just to take some time.
    End If
  End Do
  If (This_Image()==1) Then
    ! In principle we could do something with the results,
    ! but this is just a simple example.
    Call atomic_ref(mytask,ntasks)
    Print *,mytask,'tasks finished'
  End If
Contains
  Subroutine do_task(tasknum,done)
    Integer,Intent(In) :: tasknum
    Logical,Intent(Out) :: done
    Real x(tasknum)
    ! Because this is an example, we don't actually do any work.
    ! We just randomly (1% per element, i.e. approx tasknum%) set the done flag.
    ! 10% of the time we also spawn a new task (up to the maximum).
    Call random_number(x)
    If (Any(x>0.9)) Call newtask
    done = Any(x>0.99)
  End Subroutine
End Program

■ Execution Results

 30 tasks finished