home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 1B / DATAFILE_PDCD1B.iso / _pocketbk / pocketbook / 004 / ipc_zip / CTRLBEEP.DOC < prev    next >
Text File  |  1992-06-26  |  7KB  |  188 lines

  1. Simple example of InterProcessCommunication in Opl
  2. ==================================================
  3.  
  4. The two Opl programs BEEPER.OPL and CTRLBEEP.OPL demonstrate two
  5. cooperating processes.  BEEPER has two states, between which it
  6. alternates:
  7.     *  constantly beeping
  8.     *  waiting for an instruction to start beeping again
  9. CTRLBEEP contains two subroutines, NOISY: and QUIET:, which have the
  10. effect of transitioning BEEPER between its two states.
  11.  
  12. The idea of the example is that the main program is free to attend to
  13. some other activity (eg displaying a dialog, or generally interacting
  14. with the keyboard or performing some calculation), without needing to
  15. keep calling BEEP.
  16.  
  17. In the example, the routines NOISY: and QUIET: are triggered by
  18. receiving keypresses.  In a more realistic case, they could be
  19. triggered by the progress of some calculation in the main program, or
  20. by incoming serial data (etc).
  21.  
  22. The code for BEEPER.OPL
  23. -----------------------
  24.  
  25. The entire code of BEEPER.OPL is
  26.  
  27.     PROC beeper:
  28.         while 1
  29.             iowait
  30.             while peekw($28)
  31.                 beep 1,300
  32.             endwh
  33.         endwh
  34.     ENDP
  35.  
  36. The state when it is continually beeping is represented by the two
  37. lines of code
  38.  
  39.     while peekw($28)
  40.         beep 1,300
  41.  
  42. from which it is clear that it beeps beeping until the value at
  43. offset $28 becomes zero.  Evidently, the code in QUIET: in
  44. CTRLBEEP.OPL must write the value zero into this offset in the
  45. dataspace of BEEPER.  This involves an *inter process copy*.
  46.  
  47. The state in which BEEPER is waiting for another instruction to start
  48. beeping again is represented by the single line of code
  49.  
  50.     iowait
  51.  
  52. The call to iowait returns only when the BEEPER process is
  53. "signalled".  In the meantime, BEEPER sleeps (without burning round
  54. in any loop).  Evidently, the code in NOISY: in CTRLBEEP.OPL must
  55. "signal" BEEPER (and, at the same time, write a non-zero value into
  56. location $28).
  57.  
  58. Why $28 ?
  59. ---------
  60.  
  61. I chose $28 since it is the address of seven words (known as DatApp1
  62. through DatApp7) that are generally free for application programming. 
  63. They have the values 0 by default, and are guaranteed not to be
  64. altered by any system code.  (Nor will any stack, static, or heap data
  65. use these values.)
  66.  
  67. The code in QUIET:
  68. ------------------
  69.  
  70.     PROC quiet:
  71.     REM Stop beeps
  72.         local zero%
  73.         call($92,pid%,2,0,addr(zero%),$28) :rem ProcCopyToById
  74.     ENDP
  75.  
  76. The code CALL($92,...) performs the inter process copy.  The BX
  77. parameter gives the pid of the target process.  The CX parameter
  78. gives the number of bytes to copy.  The SI parameter gives the
  79. address (in the local dataspace) of the data to be copied.  The DI
  80. parameter gives the address (in the remote dataspace) where the data
  81. is to be copied.
  82.  
  83. The value of pid% has been recorded from earlier, when BEEPER was
  84. launched.
  85.  
  86. The code in NOISY:
  87. ------------------
  88.  
  89.     PROC noisy:
  90.     REM Start beeps
  91.         local one%
  92.         one%=1
  93.         call($92,pid%,2,0,addr(one%),$28) :rem ProcCopyToById
  94.         call($0986,pid%,0,0,0,0) :rem IoSignalByPid
  95.     ENDP
  96.  
  97. The main difference from QUIET: is that this time, CTRLBEEP needs to
  98. "signal" BEEPER.  This is performed by the line CALL($0986,...).  In
  99. this call, only the BX parameter matters.
  100.  
  101. (Notice that IoSignalByPid is actually a generalisation of the Opl
  102. keyword IOSIGNAL, which signals yourself - eg to ensure that you come
  103. straight out of the next call to IOWAIT).
  104.  
  105. Taking stock
  106. ------------
  107.  
  108. That's everything, apart from some housekeeping:
  109.  
  110.     CTRLBEEP has to locate and start BEEPER in the first place
  111.  
  112.     CTRLBEEP has to ensure that, whenever it is terminated, BEEPER
  113. gets tidied up too.
  114.  
  115. How CTRLBEEP starts BEEPER
  116. --------------------------
  117.  
  118. This all takes place inside the routine LAUNCHB:.  The main two lines
  119. of code are
  120.     CALL($0187,...)
  121. which creates the process, and
  122.     CALL($0688,...)
  123. which resumes the process (since all processes are initially created
  124. suspended).
  125.  
  126. The line CALL($998d,...) has the effect of placing CTRLBEEP back into
  127. foreground again (otherwise it would be displaced by BEEPER).
  128.  
  129. I haven't gone into too many details here since the same material has
  130. been covered elsewhere.
  131.  
  132. How CTRLBEEP ensures BEEPER is always terminated
  133. ------------------------------------------------
  134.  
  135. This is rather more interesting.  The routine TELLDIE: contains code
  136. to ensure that CTRLBEEP is always given warning that it ought to
  137. terminate.  The main line here is
  138.     CALL($0e88,1,...)
  139. which informs the O/S that, when this process is to be terminated
  140. from without (say because the user has pressed DELETE on this
  141. application from the System Screen - or, on the HC, because the
  142. TERMINATE command has been issued from the $ command line), then
  143. instead of simply killing it, an inter process message is to be sent
  144. to it.  The "type" of this message is specified in the BX parameter -
  145. here, 1.
  146.  
  147. Actually, the type is irrelevant for this example, since the only
  148. inter process message CTRLBEEP will ever receive is bound to be the
  149. TERMINATE one.   (The type only becomes important if there are
  150. potentially more than one possible kind of inter process message.)
  151.  
  152. Now, before calling ProcOnTerminate, it is vital to call MessInit
  153. (CALL($0083,...)) - which is a required part of the initialisation of
  154. *any* application that is going to receive inter process messaging. 
  155. Failure to call MessInit first will lead to your application being
  156. panicked.
  157.  
  158. The only significant parameter for MessInit is BX.  Actually, BX is
  159. in this case analysed as BH (the length of the extra message data),
  160. and BL (the number of message slots to reserve) (BX = BL + BH*256),
  161. but the details don't matter.  Just use $1 for the minimum overhead
  162. necessary.
  163.  
  164. Finally, CTRLBEEP has got to queue an asynchronous request to receive
  165. an inter process message.  This is the role of MessReceiveAsynchronous
  166. (CALL($0183,...)).  Here, the DI parameter must be the address of a
  167. status word which will be changed to zero when the message arrives,
  168. and the BX parameter must likewise be the address of a word
  169. essentially specifying which message slot has been used.  It turns
  170. out that CTRLBEEP never needs to read the values of either maddr% or
  171. mstat%, but if you fail to provide good addresses, random damage may
  172. ensue.
  173.  
  174. The EXIT: routine
  175. -----------------
  176.  
  177. CTRLBEEP in turn sends on a terminate message to BEEPER, using
  178. CALL($0d88,...), before STOPing itself.
  179.  
  180. Note:
  181. -----
  182.  
  183. Don't be misled: there's no need to call MessInit (or MessReceive...)
  184. just because you're doing an inter process copy or an inter proces
  185. signal.  The MessInit (and MessReceive...) is required in this
  186. example only because CTRLBEEP is potentially to receive an *interp
  187. process message* - which is a more formal construct.
  188.