[comp.lang.ada] Help me to solve this problem!

ie53@NTSUVAX.BITNET (HAERIM LEE) (08/24/87)

with text_io; use text_io;

procedure imore is      -- Intelligent 'more'

  key : character;

  task mon_user is      -- monitor user
    entry do_comm(key : character);
  end mon_user;

  task body mon_user is

    d_time : duration := 60.0;  -- pause this amount before printing next page
    frozen : boolean := FALSE;  -- true if user temporarily freeze printing

    procedure print_next is

    begin -- print_next

      put_line("Next screen");    -- simulation of printing next screen

    end print_next;

    procedure do_it(key : character) is

    begin -- do_it

      case key is
        when ' '       => print_next;           -- print next screen
        when 'f' | 'F' => frozen := TRUE;       -- freeze to read more carefully
        when 't' | 'T' => frozen := FALSE;      -- thaw (release) the freeze
        when 'c' | 'C' => d_time := 30.0;       -- change delay time
        when others    => null;                 -- ignore
      end case;

    end do_it;

  begin -- mon_user

    print_next;         -- print first page

    -- The following loop will keep printing next page every
    -- 'd_time' second, if user does not enter any command
    -- during 'd_time' seconds, or if user already has frozen
    -- automatic printing.  If he hits <space bar>, the next
    -- page is printed IMMEDIATELY, and the current printing
    -- mode is preserved.

    loop

      select
        accept do_comm(key : character) do
          do_it(key);
        end;
      or when not frozen =>
        delay d_time;           -- (roughly) suspension point 1
        print_next;
      end select;
    end loop;

  end mon_user;

begin -- imore

  -- The following loop keeps waiting for user to enter
  -- a command.  If he does, it will call the entry 'do_comm'
  -- and passes that command to it.  If no command is given
  -- within 'd_time' seconds, the next page will be automatically
  -- printed.

  loop
    get(key);                   -- suspension point 2
    mon_user.do_comm(key);
  end loop;

end imore;


-- problems statement:
--
--    This program is similar to 'more' on Unix except its more
--    clever default behavior; that is, it keeps printing each
--    page and delaying some amount of time so that user can
--    read it.  User doesn't have to hit <space bar> at all unless
--    he/she wants to wait for the next page.  It automatically
--    prints the next page after some amount of time (of cousrse,
--    user can change this value on the fly).  This is quite useful
--    if the file contains many pages which do not require careful
--    reading.  When it begins printing pages which need some
--    attention (say, need reading twice), user can freeze this
--    automatic print-pause sequence temporarily, and then use the
--    <space bar> as in the normal 'more'.  Once this portion is
--    over, he/she can resume the automatic mode printing.  With
--    this automatic printing feature and existing ones in 'more'
--    one can think about whole bunch of new functions.  It would
--    be something like a marriage of 'more' and 'cat' on Unix.
--
--    I started writing some lines of code shown above.  I expected
--    this small program would keep printing "next line" every 60
--    second if I don't hit any key after invoking this program.
--    The result, however, was quite different; only  the first
--    "next screen" is printed, and it was sitting idle until I hit
--    the <space bar>.  I noticed that this is because the 'get'
--    statement in the main body does not return its control to
--    the task 'mon_user' when it is suspended (Is it?) by this input
--    operation, while the task 'mon_user' was already in a suspended
--    state and possibly in a ready state if the specified delay time
--    had passed.  In this case, the control should be given 'mon_user'
--    so that the procedure call 'print_next' after the delay state-
--    ment can be executed.  Actually, I found that the task 'mon_user'
--    did NOT become suspended when the 'get' was invoked, but remained
--    as a 'running' state.  This can be shown using the VAX/VMS Symbolic
--    Debugger.
--
--         Shouldn't the state of the task 'mon_user' become
--    'suspended' when the 'get' is called, if there are any 'ready'
--    tasks?  If not, how do we easily implement such time-bombs for
--    input operations?  What is the relationship between task states
--    and i/o operations?  In Ada, are i/o operations done synchronously
--    or asynchronously?  Seems to be 'synchronous' in the Vax Ada V1.3.
--
--         Any comments would be appreciated.
--
--    Haerim Lee (IE53@NTSUVAX)

arny@wayback.UUCP (Arny B. Engelson) (08/26/87)

I would expect the program to do exactly what you expected it to do.

One possibility is that the delay statement is not implemented very nicely
(although still legally).  LRM 9.6:1 states "The execution of a delay statement
... suspends further execution of the task ... for AT LEAST the duration
specified ... "  [emphasis mine]

Perhaps they just decided to delay forever?

You mentioned VAX Ada; have you tried pragma Time_Slice?

How about making the "Get (Key)" part of a timed entry call, as follows:

---------------------------------------------------
task body mon is
   L_Key : Character;
begin
   loop
      Get (L_Key);
      accept Got_It (Out_Key : out Character) do
	 Out_Key := Key;
      end;
   end loop;
end;

task body imore is
begin
   loop
      select
         mon.Got_It (Key);
      or
	 delay Dur_Time;
	 Print_Next_Screen;
      end select;
   end loop;
end;
---------------------------------------------------

I know the above code is incomplete and has some bugs in it, but I'm
just trying to stimulate ideas.  Besides I only thought of it as I was
typing this article, and don't have time to go over it now.


  - Arny Engelson   {ihnp4|bonnie|clyde}!wayback!arny

jb@rti.UUCP (Jeff Bartlett) (08/27/87)

In article <8708241839.AA01159@ucbvax.Berkeley.EDU>, ie53@NTSUVAX.BITNET (HAERIM LEE) writes:

 > procedure imore is      -- Intelligent 'more'
 > 

 > This program is similar to 'more' on Unix except its more
 > clever default behavior; that is, it keeps printing each
  .....
 > "next screen" is printed, and it was sitting idle until I hit
 > the <space bar>.  I noticed that this is because the 'get'
 > statement in the main body does not return its control to
 > the task 'mon_user' when it is suspended (Is it?) by this input
 > operation, while the task 'mon_user' was already in a suspended
 > state and possibly in a ready state if the specified delay time
 > had passed.  In this case, the control should be given 'mon_user'
 > so that the procedure call 'print_next' after the delay state-
 > ment can be executed.  Actually, I found that the task 'mon_user'
 > did NOT become suspended when the 'get' was invoked, but remained
 > as a 'running' state.  This can be shown using the VAX/VMS Symbolic
 > Debugger.

 > Shouldn't the state of the task 'mon_user' become
 > 'suspended' when the 'get' is called, if there are any 'ready'
 > tasks?  If not, how do we easily implement such time-bombs for
 > input operations?  What is the relationship between task states
 > and i/o operations?  In Ada, are i/o operations done synchronously
 > or asynchronously?  Seems to be 'synchronous' in the Vax Ada V1.3.
 >
 > --    Haerim Lee (IE53@NTSUVAX)

See section 2.7 "Input-Output and Tasking" in "VAX Ada Programmer's Run-Time
Reference Manual", p 2-73.

I/O on SYS$INPUT, SYS$OUTPUT, SYS$COMMAND, and SYS$ERROR are 'synchronous'.
TEXT_IO used ADA$INPUT and ADA$OUTPUT which is normally assigned to SYS$INPUT
and SYS$OUTPUT.  To get 'async' i/o, assign ADA$INPUT and ADA$OUTPUT to TT: in
DCL.

Jeff Bartlett
Center for Digital Systems Research
Research Triangle Institute
jb@rti.rti.org

blackje%sungod.tcpip@GE-CRD.ARPA (09/01/87)

Received: by sungod.steinmetz (3.2/1.1x Steinmetz)
	id AA08368; Mon, 31 Aug 87 19:45:10 EDT
Date: Mon, 31 Aug 87 19:45:10 EDT
From: emmett black <blackje@sungod>
Posted-Date: Mon, 31 Aug 87 19:45:10 EDT
Message-Id: <8708312345.AA08368@sungod.steinmetz>
To: info-ada@ada20.isi.edu
Subject: RE: Re: Help me to solve this problem!


----- Begin Forwarded Message -----

From STRICKLER%SCOVCB.decnet@csbvax.steinmetz Mon Aug 31 13:31:03 1987
Received: from CSBVAX by sungod.steinmetz (3.2/1.1x Steinmetz)
	id AA07822; Mon, 31 Aug 87 13:30:56 EDT
Posted-Date: 31 Aug 87 13:28 EST
Message-Id: <8708311730.AA07822@sungod.steinmetz>
Date: 31 Aug 87 13:28 EST
From: STRICKLER%SCOVCB.decnet@csbvax.steinmetz
Subject: RE: Re: Help me to solve this problem!

I have not had the time to review the problem in detail, however,
I will throw out a comment which may shed some light on the problem.

Input/output operations on VAX Ada files take place sequentially
(see Programmer's Runtime Reference Manual section 2.7). Thus, if
two tasks request I/O to the same file, the second task will wait
until all previous I/O on that file is completed. 

Although I do not know for sure, VAX Ada probably treats the terminal
as a "file" and, if it does, a write can not take place while a read
is pending.


----- End Forwarded Message -----