The <tt>PROBE</tt> Statement



next up previous contents index
Next: Mapping Up: Nondeterministic Computations Previous: The MERGER Statement

The PROBE Statement

 

A process can apply the PROBE  statement to an inport to determine whether messages are pending on the associated channel. A PROBE  statement has the general form

probe(inport,empty=logical)

A logical variable specified in the EMPTY=variable  specifier is set to false if there is a message ready for receipt on the channel or if the channel has been closed (i.e., reached end-of-channel ), and to true otherwise. In other words, the EMPTY=variable specifier is set to true if a RECEIVE  on this inport would block, and to false if it would not.

In addition, IOSTAT=  and ERR=  specifiers can be included in its control list; these are as in the Fortran INQUIRE  statement. Hence, applying a PROBE  statement to an undefined port causes an integer value specified in an IOSTAT  specifier to be set to a nonzero value and causes the execution to branch to a label provided in an ERR=  specifier. See Appendix A for a list of valid IOSTAT  values.

Knowledge about sends is presumed to take a nonzero but finite time to become known to a process probing an inport. Hence, a probe of an inport that references a nonempty channel may signal true if the channel values were only recently communicated. However, if applied repeatedly without intervening receives, PROBE  will eventually signal false, and will then continue to do so until values are received.

The PROBE  statement is useful when a process wishes to interrupt local computation to handle communications that arrive at some unpredictable rate. The process alternates between performing computation and probing for pending messages, and switchs to handling messages when PROBE  returns false. For example, this is the behavior that is required when implementing a one-process-per-processor version of a branch-and-bound search algorithm. Each process alternates between advancing the local search and responding to requests for work from other processes:

==

      do while (.true.)
         call advance_local_search
         probe(requests,EMPTY=empty)
         if(.not. empty) call hand_out_work
      enddo
=1.03

The PROBE  statement can also be used to receive data that arrives in a nondeterministic  fashion from several sources. For example, the following program handles messages of types and , received on two ports, p1 and p2, respectively.

==

      process handle_msgs(p1,p2)
      inport (T1) p1
      inport (T2) p2
      ...
      do while(.true.)
         probe(p1,EMPTY=e1)
         if(.not. e1) then
            receive(p1) val1
            call handle_msg1(val1)
         endif
         probe(p2,EMPTY=e2)
         if(.not. e2) then
            receive(p2) val2
            call handle_msg2(val2)
         endif
      enddo
=1.03

A disadvantage of this program is that if no messages are pending, it consumes resources by repeatedly probing the two channels. This ``busy waiting'' strategy is acceptable if no other computation can be performed on the processor on which this process is executing. In general, however, it is preferable to use a non-busy-waiting technique. If , we can introduce a merger to combine the two message streams. The handle_msgs2 process then performs receive operations on its single inport, blocking until data is available.

==

      merger(in=pi,(out=po(i),i=1,2))
      processes
         processcall source1(po(1))
         processcall source2(po(2))
         processcall handle_msgs2(pi)
      endprocesses
=1.03

If , we can use the following technique. Each source process is augmented with an additional outport of type integer, on which it sends a distinctive message each time it sends a message. The integer outports are connected by a merger with an inport which is passed to the handle_msgs process. This process performs receive operations on the inport to determine which source process has pending messages.

==

      merger(in=ni,(out=no(i),i=1,2))
      channel(in=p1i,out=p1o)
      channel(in=p2i,out=p2o)
      processes
         processcall source1(1,p1o,no(1))
         processcall source2(2,p2o,no(2))
         processcall handle_msgs(p1i,p2i,ni)
      endprocesses

      process handle_msgs(p1,p2,pp)
      inport (T1) p1
      inport (T2) p2
      inport (integer) pp
      ...
      do while(.true.)
         receive(pp) id
         if(id .eq. 1) then
            receive(p1) val
         else
            receive(p2) val
         endif
         call handle_mesg(val)
      enddo
=1.03

 



next up previous contents index
Next: Mapping Up: Nondeterministic Computations Previous: The MERGER Statement



Steve Tuecke
Tue Aug 30 12:20:34 CDT 1994