How to terminate a timer-process with the yellow J
The following script is self-explanatory.
Try the code with JBREAK=:1 and: JBREAK=:0 .
JBREAK=:0 disables the apparatus to check the "jbreak" file, which is located in: ~temp/jbreak/ .
Then the yellow J won't (reliably) stop the animation, and you'd need to execute RUNNING_z_=: 0
e.g. by use of Ctrl+R in an IJS window.
NB. How to poll the yellow-J (jbreak) NB. IanClark Fri 27 May 2011 20:28:47 JBREAK=: 1 NB. Enable termination by Yellow-J NB. ============================================== NB. TO SEE THE EFFECT OF DISALLOWING THE YELLOW-J: NB. SET: JBREAK=: 0 NB. SINCE THE DUTY CYCLE IS TIMER-DRIVEN, NB. THE YELLOW-J DOES NOT (NORMALLY) HALT IT. NB. ============================================== NB. ----------------------- NB. Crude animation example NB. ----------------------- WORM=: '--->--->' NB. animated contents DELAY=: 0.2 NB. timer delay in SECONDS doframe=: 3 : 0 NB. draw next animation frame smclear'' smoutput 8$'=' smoutput WORM=: _1 |. WORM ) duty_cycle=: 3 : 0 NB. animation duty-cycle firstpass=. y NB. (This may differ in future versions) doframe'' if. firstpass do. sess 'duty_cycle:' ; 'firstpass' JBD=: 1!:0< JBF=: 9!:46'' NB. dir and pathname of jbreak file RUNNING_z_=: 1 NB. in z-locale --> seen everywhere end. NB. If jbreak dir has changed, halt duty cycle ... if. JBREAK *. -. JBD-: 1!:0< JBF do. RUNNING_z_=: 0 end. if. RUNNING do. DELAY timexec 'duty_cycle 0' else. sess 'duty_cycle:' ; 'RUNNING=' ; RUNNING end. ) immx=: runimmx1_jijs_ NB. this version echoes: y immx=: runimmx0_jijs_ NB. this version is silent nb=: [: ([: }. ([: ; (' ' (,&.>) ]))) (":&.>) run=: duty_cycle bind 1 sess=: smoutput @ nb NB. boxed output --> 1 line smclear=: 3 : 0 NB. clear the IJX window try. if. IFIJX_0_ do. NB. provided locale 0 is IJX... wd 'psel ',SMHWNDP_0_ wd 'set e ""' else. @@ NB. force an error end. catch. smoutput 'smclear: cannot identify J session window' end. ) timexec=: 3 : 0 NB. execute stmt: y ONCE after x msec DELAY timexec y : sess=. empty NB. comment-out this line for trace NB. x is msec delay before executing phrase: y NB. if x<0 stop systimer and immx: y NB. if x=0 simply stop systimer. if. x=0 do. wd 'timer 0' sess 'timexec:' ; 'stop systimer' elseif. x<0 do. immx y [ wd 'timer 0' sess 'timexec:' ; 'stop systimer and execute:' ; y elseif. x>0 do. sys_timer_z_=: (_1&timexec) bind y wd nb 'timer' ; (<.x*1000) NB. x is in SECONDS sess 'timexec: after' ; x ; 'seconds execute:' ; y end. ) smoutput 0 : 0 NB. To run the demo... run'' NB. or... duty_cycle 1 NB. To stop the animation, launch jbreak (the yellow J). NB. Alternatively re-enter (Ctrl+R) one of these lines... RUNNING_z_=: 0 NB. flag: 1= continue the duty cycle 0 timexec 0 NB. stop systimer wd 'timer 0' NB. stop systimer directly )
The principle is simple. When the yellow-J is launched, it updates the timestamp of the "jbreak" file. The verb duty_cycle fetches the directory entry of this file (which contains the timestamp) and watches for it to change.
This kind of duty cycle does not use a repeating timer. To achieve better control (during development) the verb duty_cycle sets systimer to call itself once-only after a given time interval (DELAY). It then turns off the timer and performs some checks (including reading the flag RUNNING_z_) and only if it is happy will it set the timer again for another duty cycle. This allows the J user to carry on with coding tasks in the foreground (which may give errors), with the duty cycle running invisibly in the background and trying to stay out of the way. And if duty_cycle is knocked off its horse, it doesn't get dragged along by the reins.
However if you want to use a repeating timer, the technique is similar, but you must stop systimer directly, using (wd 'timer 0').