Hi, Some days ago, searching for info on Gforth's multitasking, I found a link Anton Ertl mentioned in <comp.alt.forth> (http://compgroups.net/comp.lang.forth/looking-for-more-gforth-documentation/1259909): <http://egesund.org/forth/forth.htm>.
With the help of that little example and Gforth's <tasker.fs>, I did many tries and finally understood how the thing works. I wrote four little demos. The last one shows two counters on the screen while the input line works normally. One interesting problem was how to manage the cursor: the word used to get the current cursor position, 'xy', uses 'key', so the normal (say "non-multitasking") 'key' has to be reactivated before executing 'xy'. Another problem was at first the tasks run only when a key was pressed. The reason was Gforth's 'u8key' is not affected by changing the action of 'key' because it's written with 'defers key'. Is there any reason for that? Finally I decided to write a modified version of 'u8key', 'task-u8key'. Since multitasking is not documented in Gforth (yet), I think my tries can be useful to others. I will publish them in my website as soon as possible and will announce here; but here you are the last one, the most interesting: ========================= START OF CODE ======================== \ multitasking_test_03.fs \ \ Test program \ to learn how to use the Gforth's multitasking. \ \ By Marcos Cruz (programandala.net) \ \ Change log: \ \ 2013-06-27 Start. First working version. \ 2013-07-09 <galope/xy.fs> temporarily merged. \ ************************************************************** \ Requirements \ Save the original behaviour of 'key', \ before the tasker changes it: ' key defer@ constant ((key)) require tasker.fs require random.fs false [if] require galope/xy.fs [else] \ ----8<-------------------------------------------------------- \ galope/xy.fs \ Current cursor coordinates \ This file is part of Galope \ (Gforth Accessory Library of Particular Elements) \ Extracted and modified from: \ ansi.4th \ ANSI Terminal words for kForth \ Copyright (c) 1999--2004 Krishna Myneni \ Creative Consulting for Research and Education \ This software is provided under the terms of the GNU \ General Public License. \ Modifications: \ Copyright (C) 2012 Marcos Cruz (programandala.net) \ History \ 2012-04 Extracted from a program of mine. \ 2012-04-29 Added 'at-x' and 'at-y'. \ 2012-05-08 'at-x' and 'at-y' moved to their own files. \ 2013-06-26 Fixed some comments. \ 2013-06-26 Gforth's 'esc[' used instead of 'ansi_escape'. base @ decimal : number<c> ( c -- n ) \ Read a decimal numeric entry delimited by character c. \ xxx todo move this word to its own file: \ xxx todo choose a better name?: \ number/c \ keys/c>decimal \ keys># \ keys>number \ keys>#number \ xxx todo no final char: finish at the first non-digit instead >r 0 begin key dup r@ <> while swap 10 * swap '0' - + repeat r> 2drop ; : xy ( -- u1 u2 ) \ Return the current cursor position. \ u1 = current column \ u2 = current line esc[ ." 6n" key key 2drop \ erase: <esc> [ ';' number<c> 'R' number<c> 1- swap 1- ; base ! \ ----8<-------------------------------------------------------- [then] \ ************************************************************** \ Main 16 newtask constant taksk_1_id 16 newtask constant taksk_2_id : task-u8key ( -- u ) \ Multitasking version of Gforth's u8key (defined in <utf-8.fs>). \ Changes: 'defers key' to 'task-key'. task-key dup max-single-byte u< ?exit \ special case ASCII dup $ff = ?exit \ special resize character dup $c2 u< if utf-8-err throw then \ malformed character $7f and $40 >r begin dup r@ and while r@ xor 6 lshift r> 5 lshift >r >r task-key dup $c0 and $80 <> if utf-8-err throw then $3f and r> or repeat rdrop ; : untasked_output ( -- ) \ Set the basic output words to their non-multitasking defaults. ['] (emit) is emit ['] (type) is type ; : tasked_output ( -- ) \ Set the basic output words to their multitasking versions. ['] task-emit is emit ['] task-type is type ; : untasked_key ( -- ) \ Set 'key' to its non-multitasking default. ((key)) is key ; : untasked_xkey ( -- ) \ Set 'xkey' to its non-multitasking default. ['] u8key is xkey ; : untasked_input ( -- ) \ Set the basic input words to their non-multitasking defaults. untasked_key untasked_xkey ; : tasked_key ( -- ) \ Set 'key' to its multitasking version. ['] task-key is key ; : tasked_xkey ( -- ) \ Set 'xkey' to its multitasking version. ['] task-u8key is xkey ; : tasked_input ( -- ) \ Set the basic input words to their multitasking versions. tasked_key tasked_xkey ; ' page alias (page) \ original 'page' defer page : tasked_page ( -- ) \ Safe version of 'page' when multitasking. untasked_output (page) tasked_output ; ' tasked_page is page : (xy) ( -- u1 u2 ) \ Safe version of 'xy' when multitasking. untasked_key xy tasked_key ; 2048 value /ms \ interval : time? ( -- flag ) \ Is it time to execute a task? utime drop /ms mod 0= ; variable counter1 : (task1) ( -- ) 1 counter1 +! untasked_output (xy) 0 0 at-xy counter1 ? at-xy tasked_output ; : task1 ( -- ) taksk_1_id activate begin time? if (task1) then pause again ; variable counter2 : (task2) ( -- ) 10 counter2 +! untasked_output (xy) 10 10 at-xy counter2 ? at-xy tasked_output ; : task2 ( -- ) taksk_2_id activate begin time? if (task2) then pause again ; : run ( -- ) page task1 task2 untasked_output 0 rows 3 - at-xy ." The counters run even when no key is pressed." tasked_input ; page .( multitasking_test_03.fs) cr .( Type RUN to start the demo.) cr cr ========================== END OF CODE ========================= I'd appreciate any comment, correction or improvement. Has someone written other examples or documentation on multitasking? Thank you. Marcos -- http://programandala.net