home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1986 / 03 / berglst2.mar < prev    next >
Text File  |  1986-03-31  |  6KB  |  222 lines

  1. {task #1: keyboard -> fifo1
  2.  task #2: fifo1    -> filter -> fifo2
  3.  task #3: fifo2    -> slow display    }
  4. program main;
  5. const   TASKS=3;
  6.         STACKSIZE=20;
  7.         NFIFOS=2;{#1 is for input and #2 for output}
  8.         PRATE=300;{SLOWs the display function}
  9. {the following three constants are for the Kaypro Computer}
  10.         KDATA=5; KSTAT=7; RMASK=1;
  11.         CR=13;
  12.         LF=10;
  13.         CC=3;
  14.         BS=8;
  15.         RUB=127;
  16.         SPACE=32;
  17.         CQ=17;{XON}
  18.         CS=19;{XOFF}
  19. type    stack = array[0..STACKSIZE] of integer;
  20.         fifo = record
  21.                buf: array[0..255] of byte;
  22.                inptr: byte;
  23.                outptr: byte;
  24.                flow: boolean;{for flow control}
  25.                end;
  26.         fifon = 1..NFIFOS;
  27.         tasknum = -1.. TASKS;
  28. var     sp0,sp1,sp2,sp3: integer;{when zero, task not initialized}
  29.         oldn: tasknum;
  30.         nextn: tasknum;
  31.         fifos: array[1..NFIFOS] of fifo;
  32. Procedure defer; forward;
  33. function occupancy(p: fifon):byte;
  34.          begin with fifos[p] do
  35.          occupancy:= inptr-outptr;
  36.          end;
  37. function vacancy(p: fifon): byte;
  38.          begin with fifos[p] do
  39.          vacancy:=outptr-inptr-1;
  40.          end;
  41. function dequeue1: byte;
  42.          begin with fifos[1] do
  43.          begin
  44.          while (occupancy(1)=0) or not flow
  45.                do defer;
  46.          dequeue1:= buf[outptr];
  47.          outptr:=outptr+1;
  48.          end;
  49.          end;
  50. function dequeue2: byte;
  51.          begin with fifos[2] do
  52.          begin
  53.          while (occupancy(2)=0) or not flow
  54.                do defer;
  55.          dequeue2:= buf[outptr];
  56.          outptr:=outptr+1;
  57.          end;
  58.          end;
  59. procedure exit;
  60.           begin
  61.           writeln('JOB #',oldn,' terminated.');
  62.           oldn:=-1;
  63.           defer;
  64.           end;
  65. procedure enqueue1(b:byte);
  66.           begin with fifos[1] do
  67.           begin
  68.           buf[inptr]:=b;
  69.           while vacancy(1)=0 do
  70.              defer;{hang while full}
  71.           inptr:=inptr+1;
  72.           end;
  73.           end;
  74. procedure enqueue2(b:byte);
  75.           begin with fifos[2] do
  76.           begin
  77.           buf[inptr]:=b;
  78.           while vacancy(2)=0 do
  79.              defer;{hang while full}
  80.           inptr:=inptr+1;
  81.           end;
  82.           end;
  83. function keyin:byte;
  84.          begin
  85.            repeat until (RMASK = (RMASK and port[KSTAT]));
  86.            keyin:= port[KDATA];
  87.          end;
  88. procedure vout(b:byte);
  89.           begin
  90.           bdos(6,b);
  91.           end;
  92. Procedure print;{task#3}
  93. var       mystack: stack;
  94.           i: integer;
  95.           begin
  96.           stackptr:=addr(mystack[STACKSIZE]);
  97.           i:=0;
  98.           {initialize fifo#2}
  99.           with fifos[2] do
  100.                begin
  101.                outptr:=0;
  102.                inptr:=0;
  103.                flow:=true;
  104.                end;
  105.           repeat
  106.             i:=i+1;
  107.             if i=PRATE then
  108.                begin
  109.                i:=0;
  110.                vout(dequeue2);
  111.                end
  112.             else
  113.                defer;
  114.           until false;{forever}
  115.           exit;
  116.           end;
  117. Procedure keyboard;{task #1}
  118. var       mystack: stack;
  119.           cb: byte;
  120.           begin
  121.           stackptr:=addr(mystack[STACKSIZE]);
  122.           {initialize fifo #1}
  123.           with fifos[1] do
  124.                begin
  125.                inptr:=0;
  126.                outptr:=0;
  127.                flow:=true;
  128.                end;
  129.           repeat
  130.             if (1 = (1 and port[KSTAT]))
  131.             then
  132.               begin
  133.               cb:= port[KDATA];
  134.               enqueue1(cb);
  135.               end
  136.             else defer;
  137.           until false{forever};
  138.           exit;
  139.           end;
  140. Procedure filter;{task #2}
  141. var       mystack: stack;
  142.           b: byte;
  143.           begin
  144.           stackptr:=addr(mystack[STACKSIZE]);
  145.           repeat
  146.             b:=dequeue1;
  147.             case b of
  148.             CR: begin
  149.                 enqueue2(CR);
  150.                 enqueue2(LF);
  151.                 end;
  152.             LF: {ignore};
  153.             CC: exit;
  154.             BS,RUB:
  155.                begin
  156.                enqueue2(BS);
  157.                enqueue2(SPACE);
  158.                enqueue2(BS);
  159.                end;
  160.             CQ: fifos[2].flow:=true;
  161.             CS: fifos[2].flow:=false;
  162.             else enqueue2(b);
  163.             end{case};
  164.           until false;{forever!}
  165.           exit;
  166.           end;
  167. procedure initall;
  168. var       i: integer;
  169.           Begin
  170.           sp1:=0;
  171.           sp2:=0;
  172.           sp3:=0;
  173.           oldn:=0;
  174.           end;
  175. Procedure schedule;
  176.           begin
  177.           if oldn=TASKS then nextn:=1
  178.           else nextn:=oldn+1;
  179.           end;
  180. procedure defer;
  181. var sp: integer;
  182.           begin
  183.            case oldn of
  184.            0: sp0:=stackptr;
  185.            1: sp1:=stackptr;
  186.            2: sp2:=stackptr;
  187.            3: sp3:=stackptr;
  188.            end{case};
  189.         schedule;
  190.         oldn:=nextn;
  191.         case nextn of
  192.         0: sp:=sp0;
  193.         1: sp:=sp1;
  194.         2: sp:=sp2;
  195.         3: sp:=sp3;
  196.         end{case};
  197.         if sp<>0 {initialized}
  198.         then begin
  199.           stackptr:=sp;
  200.              end
  201.         else {not initialized}
  202.              begin
  203.              case nextn of
  204.              1: keyboard;
  205.              2: filter;
  206.              3: print;
  207.              end{case};
  208.              end;
  209.      end{defer};
  210. begin{main}
  211. initall;
  212. writeln('<Demonstration of multitasking with queues (FIFOs)>');
  213. writeln;
  214. writeln('Control-S stops output (you can still type ahead!)');
  215. writeln('Control-Q restarts output (you can see what you have typed ahead)');
  216. writeln('RUB or BACKSPACE will "undo" on screen the last letter');
  217. writeln('Control-C terminates this program');
  218. writeln;
  219. defer;
  220. writeln('main: done');
  221. end.
  222.