From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-0.8 required=5.0 tests=BAYES_00,INVALID_DATE, MSGID_SHORT autolearn=no autolearn_force=no version=3.4.4 Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!cs.utexas.edu!usc!sdsu!ucsd!ucsdhub!hp-sdd!ncr-sd!ncrcae!hubcap!wtwolfe From: wtwolfe@hubcap.clemson.edu (Bill Wolfe) Newsgroups: comp.lang.ada Subject: Interactive I/O in Ada Message-ID: <7701@hubcap.clemson.edu> Date: 19 Jan 90 04:01:52 GMT Organization: Clemson University, Clemson, SC List-Id: In the current issue of ACM SIGAda Ada Letters, Doug Bryan provides a simple answer to a commonly asked question: How does one do keyboard input in Ada while having other tasks do some work in the background in between keystrokes? Since Text_IO generally is not implemented so as to permit this to be done trivially, it is necessary to isolate the task which is handling the keyboard; the keyboard-handling task repeatedly calls Text_IO.Get to obtain a character and deposits it into a virtual keyboard. The tasks which are to run in the background can then make their entry calls to the virtual keyboard, such that a rendezvous will only occur if a character is waiting to be consumed. Sample code (Bryan's solution, with improved documentation) follows: task Keyboard is -- Keyboard abstraction, for use by other tasks entry Read (Next_Character : in Character); -- Other tasks call... entry Write (Next_Character : out Character); -- Only handler calls... end Keyboard; task Keyboard_Handler; with Text_IO; task body Keyboard_Handler is Character_Buffer : Character; begin loop Text_IO.Get (Character_Buffer); Keyboard.Write (Character_Buffer); end loop; end Keyboard_Handler; with Generic_Queue; -- You'll need to write this generic package, to -- provide type Queue with operations Enqueue, -- Dequeue, and Empty. task body Keyboard is package Character_Queue_Handler is new Generic_Queue (Character); use Character_Queue_Handler; Character_Queue : Character_Queue_Handler.Queue; begin loop select accept Write (Next_Character : in Character) do Enqueue (Character_Queue, Next_Character); end Write; or when not Empty (Character_Queue) => accept Read (Next_Character : out Character) do Dequeue (Character_Queue, Next_Character); end Read; or terminate; end select; end loop; end Keyboard; -- To use this keyboard abstraction, write code along these lines: -- -- loop -- select -- Keyboard.Read (Keystroke); -- Keystroke is of type Character -- -- code to process a keystroke -- else -- -- code to do other work "in the background" -- end select; -- end loop; -- -- On each pass through the loop, if a character is available for -- immediate consumption, the code to process a keystroke will be -- executed. If a character is not immediately available, then the -- code to do other work "in the background" will be executed. The -- code to process a keystroke will normally contain an exit statement -- whereby the loop is exited once continued monitoring of the keyboard -- is no longer desired (e.g., the user indicates a wish to exit this -- mode of interaction). The code to do other work in the background -- will normally be set up to do small increments of work in order to -- maintain a reasonable level of user responsiveness. Bill Wolfe, wtwolfe@hubcap.clemson.edu