|
| 1 | +! async-hello-2015.f90 |
| 2 | +! |
| 3 | +! -- A Parallel "Hello World" program in Fortran 2015: |
| 4 | +! Image 1 asynchronously gets and prints greetings defined by every image. |
| 5 | +! |
| 6 | +! The program uses event post, query, and wait defined by a Fortarn 2015. |
| 7 | +program main |
| 8 | + use iso_fortran_env, only : event_type,output_unit |
| 9 | + implicit none |
| 10 | + |
| 11 | + character(len=48) :: greeting[*] |
| 12 | + type(event_type), allocatable :: greeting_ready(:)[:] |
| 13 | + type(event_type) :: ok_to_overwrite[*] |
| 14 | + integer :: step |
| 15 | + integer, parameter :: nsteps=4 |
| 16 | + |
| 17 | + associate( me=>this_image(), ni=>num_images() ) |
| 18 | + |
| 19 | + allocate(greeting_ready(ni)[*]) |
| 20 | + |
| 21 | + do step=1,nsteps |
| 22 | + |
| 23 | + if (me/=1) then |
| 24 | + ! Wait for image 1 signal that it has the previous greeting |
| 25 | + if (step>1) event wait( ok_to_overwrite ) ! Atomically decrements my ok-to-write counter |
| 26 | + write(greeting,"(3(a,i2))") "Greetings from image ",me," of ",ni," on step ",step |
| 27 | + ! Signal image 1 that a new greeting is ready for pickup: |
| 28 | + event post(greeting_ready(me)[1]) ! Atomically increments my event greeting-ready counter on image 1 |
| 29 | + |
| 30 | + else |
| 31 | + |
| 32 | + write(greeting,"(3(a,i2))") "Greetings from image ",me," of ",ni," on step ",step |
| 33 | + |
| 34 | + spin_query_work: block |
| 35 | + integer :: image,ready_count |
| 36 | + integer, save, allocatable :: previous_count(:) |
| 37 | + logical, dimension(2:ni) :: greeting_not_printed |
| 38 | + integer, parameter :: max_single_digit=9 |
| 39 | + |
| 40 | + if (.not. allocated(previous_count)) allocate(previous_count(2:ni),source=0) |
| 41 | + |
| 42 | + greeting_not_printed=.true. |
| 43 | + |
| 44 | + spin: do while( any( greeting_not_printed ) ) ! Loop until all greetings have been printed |
| 45 | + query: do image=2,min(ni,max_single_digit) ! Atomically access each event's counter |
| 46 | + if (greeting_not_printed(image)) then ! Print greetings that have not been printed during this step |
| 47 | + call event_query( greeting_ready(image), ready_count) |
| 48 | + work_if_ready: select case(ready_count-previous_count(image)) |
| 49 | + case(0) ! keep spinning until greeting is ready |
| 50 | + case(1) ! event posted so get and print greeting |
| 51 | + write(greeting,"(2(a,i2))") greeting[image] |
| 52 | + associate(expected_location=>23) |
| 53 | + ! Verify that the greetings of images 1-9 have their image number at the expected location: |
| 54 | + if (scan(greeting,set="123456789")/=expected_location) error stop "Test failed." |
| 55 | + end associate |
| 56 | + event post(ok_to_overwrite[image]) |
| 57 | + greeting_not_printed(image)=.false. |
| 58 | + previous_count(image)=ready_count |
| 59 | + case default |
| 60 | + if (ready_count<0) error stop "compiler bug: negative event_query count" |
| 61 | + error stop "multiple events happened since last the last event query" |
| 62 | + end select work_if_ready |
| 63 | + end if |
| 64 | + end do query |
| 65 | + end do spin |
| 66 | + |
| 67 | + end block spin_query_work |
| 68 | + end if |
| 69 | + end do |
| 70 | + |
| 71 | + sync all |
| 72 | + if (me==1) print *,"Test passed." |
| 73 | + |
| 74 | + end associate |
| 75 | + |
| 76 | + |
| 77 | +end program |
0 commit comments