wtwolfe@hubcap.clemson.edu (Bill Wolfe) (01/19/90)
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
harold@harvax.UUCP (Harold Rabbie) (01/24/90)
Bill Wolfe writes: >> 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 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ My question is: WHY NOT? The reason TEXT_IO isn't pre-emptible on most systems is that the scheduler in the underlying OS isn't aware of the Ada tasking scheduler. It blocks on the call to read() or whatever, never allowing the Ada scheduler to regain control. This is just a BAD IMPLEMENTATION. There's no reason why TEXT_IO shouldn't check before issuing a potentially blocking system call, and then use an asynchronous type of request. Better yet, on embedded systems, you can use an operating system that only has a single level of scheduling. If an Ada task makes a blocking call, like TEXT_IO, then the scheduler can find another Ada task to run. Moral of the story: if real-time I/O is important to you, then use a real-time Ada OS. Accept no substitute. --------------------------+-------------------------------------------- Harold Rabbie, Ready Systems "when REAL_TIME => accept READY_SYSTEMS;" UUNET: {sun!pyramid,hplabs}!harvax!harold ARPA: rabbieh@ajpo.sei.cmu.edu --------------------------+--------------------------------------------
falis@ajpo.sei.cmu.edu (Edward Falis) (01/25/90)
Without getting too commercial here, your best bet on this issues is to check with the vendor. Several vendors do provide this facility: a task about to block on an I/O operation relinquished the processor so another task caN be scheduled. This is actually fairly trivial to implement when an Ada task directly issues the I/O operation request. Where it gets more interesting is when an Ada task calls interfaced code (EG third party software) which issues an I/O call which will block. ps most Ada systems intended for use on bare targets include an "Ada OS" - Ed Falis, Alsys Inc.