home *** CD-ROM | disk | FTP | other *** search
/ C!T ROM 2 / ctrom_ii_b.zip / ctrom_ii_b / PROGRAM / PASCAL / MULTI12 / MUL_DEMO.PAS < prev    next >
Pascal/Delphi Source File  |  1989-06-04  |  14KB  |  654 lines

  1. program MultiDemo;
  2.  
  3. { Demonstrates the capabilities of the Multi unit }
  4.  
  5. uses multi,crt,dos;
  6.  
  7. type  ScreenState = (free, used);          { Is screen position free? }
  8.  
  9.       BufferType  = Record                 { Declaration of messages to be }
  10.                       p1,p2  : Pointer;    { sent to message semaphores }
  11.                       number : Integer;
  12.                     End;
  13.  
  14.       WindowType  = Record                 { Window descriptor }
  15.                       X,
  16.                       Y,
  17.                       Xsize,
  18.                       Ysize  : Integer;
  19.                     End;
  20.  
  21.  
  22. var   screen      : Array(.0..81,0..26.) of ScreenState;
  23.       WindowTable : Array(.1..20.) of WindowType;
  24.  
  25.       DosSem,                              { Semaphores used to guard }
  26.       CrtSem,                              { non-shareble resources: DOS, }
  27.       KbdSem      : Semaphore;             { screen and keyboard }
  28.  
  29.       WindowSem,                           { Message semaphores used for }
  30.       NumberSem,                           { communication between processes }
  31.       PrimeSem,
  32.       BufferSem1,
  33.       BufferSem2,
  34.       BallSem     : MsgSemaphore;
  35.  
  36.       i,j,                                 { Index variables }
  37.       NoWindows   : Integer;               { No. of windows on screen }
  38.  
  39.       proc1,                               { Handles on process descriptors }
  40.       proc2,
  41.       proc3,
  42.       proc4,
  43.       proc5,
  44.       proc6,
  45.       proc7,
  46.       proc8       : Process;
  47.  
  48.       buf         : ^BufferType;
  49.       ptr         : Pointer;
  50.  
  51.  
  52. Procedure SetCursor(Cursor: Word);
  53.  
  54. { Sets cursortype according to Cursor }
  55.  
  56.    var  Reg : Registers;
  57.  
  58.    begin
  59.      with Reg do
  60.      begin
  61.        AH := 1;
  62.        BH := 0;
  63.        CX := Cursor;
  64.        Intr($10, Reg);
  65.      end; { with }
  66.    end; { SetCursor }
  67.  
  68.  
  69. Procedure MakeWindow(X, Y, Xsize, Ysize: Integer; Heading: String);
  70.  
  71. { Reserves screenspace for window and draws border around it }
  72.  
  73.    const NEcorner = #187;                { Characters for double-line border }
  74.          SEcorner = #188;
  75.          SWcorner = #200;
  76.          NWcorner = #201;
  77.          Hor      = #205;
  78.          Vert     = #186;
  79.  
  80.    var   i,j : Integer;
  81.  
  82.    Begin
  83.      Window(1,1,80,25);
  84.  
  85.      { Reserve screen space }
  86.      For i:=X to X+Xsize-1 Do
  87.        For j:=Y to Y+Ysize-1 Do screen(.i,j.):=used;
  88.  
  89.      { Draw border - sides }
  90.      i:=X;
  91.      For j:=Y+1 to Y+Ysize-2 Do
  92.      Begin
  93.        GotoXY(i,j);
  94.        Write(Vert);
  95.      End;
  96.  
  97.      i:=X+Xsize-1;
  98.      For j:=Y+1 to Y+Ysize-2 Do
  99.      Begin
  100.        GotoXY(i,j);
  101.        Write(Vert);
  102.      End;
  103.  
  104.      j:=Y;
  105.      For i:=X+1 to X+Xsize-2 Do
  106.      Begin
  107.        GotoXY(i,j);
  108.        Write(Hor);
  109.      End;
  110.  
  111.      j:=Y+Ysize-1;
  112.      For i:=X+1 to X+Xsize-2 Do
  113.      Begin
  114.        GotoXY(i,j);
  115.        Write(Hor);
  116.      End;
  117.  
  118.      { Draw border - corners }
  119.      GotoXY(X,Y);
  120.      Write(NWcorner);
  121.      GotoXY(X+Xsize-1,Y);
  122.      Write(NEcorner);
  123.      GotoXY(X+Xsize-1,Y+Ysize-1);
  124.      Write(SEcorner);
  125.      GotoXY(X,Y+Ysize-1);
  126.      Write(SWcorner);
  127.  
  128.      { Make Heading }
  129.      GotoXY(X+(Xsize-Length(Heading)) div 2,Y);
  130.      Write(heading);
  131.  
  132.      { Save in table }
  133.      NoWindows:=NoWindows+1;
  134.      WindowTable(.NoWindows.).X:=X;
  135.      WindowTable(.NoWindows.).Y:=Y;
  136.      WindowTable(.NoWindows.).Xsize:=Xsize;
  137.      WindowTable(.NoWindows.).Ysize:=Ysize;
  138.  
  139.    End; { MakeWindow }
  140.  
  141.  
  142. Procedure SelectWindow(i : Integer);
  143.  
  144.    { Specifies which window will receive subsequent output }
  145.  
  146.    Begin
  147.      With WindowTable(.i.) Do
  148.      Begin
  149.        Window(X+1,Y+1,X+Xsize-2,Y+Ysize-2);
  150.      End;
  151.    End; { SelectWindow }
  152.  
  153.  
  154. Procedure RemoveWindow(n: Integer);
  155.  
  156.    { Removes window number n }
  157.  
  158.    var i,j : Integer;
  159.  
  160.    Begin
  161.      Wait(CrtSem);
  162.      SelectWindow(n);
  163.      With WindowTable(.n.) Do
  164.      Begin
  165.        Window(X,Y,X+Xsize,Y+Ysize);
  166.        For i:=X to X+Xsize Do
  167.          For j:=Y to Y+Ysize Do screen(.i,j.):=free;
  168.      End; { With }
  169.      ClrScr;
  170.      Signal(CrtSem);
  171.    End; { SelectWindow }
  172.  
  173.  
  174. Procedure Delay(DelayTime : Word);
  175.  
  176. { Waits DelayTime seconds before returning - Does busy waiting }
  177.  
  178.    var ReturnTime,
  179.        Hour,
  180.        Minute,
  181.        Second,
  182.        Sec100     : Word;
  183.  
  184.    Begin
  185.      Wait(DosSem);
  186.      GetTime(Hour,Minute,Second,Sec100);
  187.      Signal(DosSem);
  188.      ReturnTime:=(Second+DelayTime) Mod 60;
  189.  
  190.      Repeat
  191.        Wait(DosSem);
  192.        GetTime(Hour,Minute,Second,Sec100);
  193.        Signal(DosSem);
  194.      Until
  195.        Second=ReturnTime;
  196.    End; { Delay }
  197.  
  198.  
  199. Procedure ball;
  200.  
  201. { flies a ball around the screen bouncing off windowes }
  202.  
  203.    const ball = #09;
  204.  
  205.    var   x,y,
  206.          dx,dy,
  207.          len   : Real;
  208.          Msg   : Pointer;
  209.  
  210.    Begin
  211.      { Start ball at random free position }
  212.      Randomize;
  213.      Repeat
  214.         x:=Random*80+1;
  215.         y:=Random*25+1;
  216.      Until
  217.         screen(.trunc(x),trunc(y).)=free;
  218.  
  219.      { Choose random velocities }
  220.      dx:=Random-0.5;
  221.      dy:=(Random-0.5)/2;
  222.      len:=sqrt(dx*dx+dy*dy)*1.5;
  223.      dx:=dx/len;
  224.      dy:=dy/len;
  225.  
  226.      Repeat
  227.        While screen(.trunc(x+dx),trunc(y+dy).)=used Do
  228.        Begin
  229.          If trunc(y)<>trunc(y+dy)
  230.          Then dy:=-dy+(Random-0.5)/20;
  231.          If trunc(x)<>trunc(x+dx)
  232.          Then dx:=-dx+(Random-0.5)/10;
  233.          len:=sqrt(dx*dx+dy*dy)*1.5;
  234.          dx:=dx/len;
  235.          dy:=dy/len;
  236.        End;
  237.  
  238.        Wait(CrtSem);
  239.        Window(1,1,80,25);
  240.        GotoXY(trunc(x+dx),trunc(y+dy));
  241.        write(ball);
  242.        GotoXY(trunc(x),trunc(y));
  243.        write(' ');
  244.        Signal(CrtSem);
  245.  
  246.        x:=x+dx;
  247.        y:=y+dy;
  248.  
  249.        GetMsg(BallSem,Msg,Return);
  250.      Until
  251.        Msg<>nil;
  252.  
  253.        GotoXY(trunc(x),trunc(y));
  254.        write(' ');
  255.  
  256.        die;
  257.    End; { ball }
  258.  
  259.  
  260. Procedure numbers;
  261.  
  262. { Generates numbers to be tested for prime-ness and sends them to the
  263.   message semaphore NumberSem. }
  264.  
  265.   var i      : Integer;
  266.       buf    : ^BufferType;
  267.       ptr    : Pointer;
  268.  
  269.   Begin
  270.     For i:=2 to Maxint Do
  271.     Begin
  272.       { Reserve screen and print message }
  273.       Wait(CrtSem);
  274.       SelectWindow(2);
  275.       ClrScr;
  276.       Writeln;
  277.       Write(' Sending ',i,'...');
  278.       Signal(CrtSem);
  279.  
  280.       { Request buffer and send number }
  281.       GetMsg(BufferSem1,ptr,stay);
  282.       buf:=ptr;
  283.       buf^.number:=i;
  284.       PutMsg(NumberSem,ptr);
  285.     End;
  286.  
  287.     Die;
  288.   End; { Numbers }
  289.  
  290.  
  291. Procedure TestNumber;
  292.  
  293. { Tests a number from NumberSem for prime-ness. If it is a prime, it is
  294.   sent to PrimeSem }
  295.  
  296.   var buf    : ^BufferType;
  297.       ptr    : Pointer;
  298.       window,
  299.       i,
  300.       number : Integer;
  301.       prime  : Boolean;
  302.  
  303.  
  304.   Begin
  305.     { Get allocated windownumber }
  306.     GetMsg(WindowSem,ptr,stay);
  307.     buf:=ptr;
  308.     Window:=buf^.number;
  309.  
  310.     { Return buffer to pool }
  311.     PutMsg(BufferSem1,ptr);
  312.  
  313.     Repeat
  314.       { Get a number to test }
  315.       GetMsg(NumberSem,ptr,stay);
  316.       buf:=ptr;
  317.       Number:=buf^.Number;
  318.       PutMsg(BufferSem1,ptr);
  319.  
  320.       { Is it a death sentence? }
  321.       If number<0 Then
  322.       Begin
  323.         Wait(CrtSem);
  324.         SelectWindow(Window);
  325.         ClrScr;
  326.         HighVideo;
  327.         Write('Arrgghh....');
  328.         NormVideo;
  329.         Signal(CrtSem);
  330.  
  331.         Delay(5);
  332.  
  333.         RemoveWindow(Window);
  334.         Die;
  335.       End; { If }
  336.  
  337.       { Announce test }
  338.       Wait(CrtSem);
  339.       SelectWindow(Window);
  340.       ClrScr;
  341.       Write('Testing ',Number);
  342.       Signal(CrtSem);
  343.  
  344.       { Do test }
  345.       i:=2;
  346.       prime:=true;
  347.       While prime and (i<=Sqrt(Number)) Do
  348.       Begin
  349.         prime:=(number mod i<>0);
  350.         inc(i);
  351.       End;
  352.  
  353.       If prime
  354.       Then Begin
  355.              Wait(CrtSem);
  356.              SelectWindow(Window);
  357.              ClrScr;
  358.              Write(Number,' is a prime!');
  359.              Signal(CrtSem);
  360.  
  361.              GetMsg(BufferSem2,ptr,stay);
  362.              buf:=ptr;
  363.              buf^.number:=number;
  364.              PutMsg(PrimeSem,ptr);
  365.            End
  366.       Else Begin
  367.              Wait(CrtSem);
  368.              SelectWindow(Window);
  369.              ClrScr;
  370.              Writeln('Shucks! ',number,' is');
  371.              Write('divisible by ',i-1);
  372.              Signal(CrtSem);
  373.            End;
  374.     Until
  375.        false;
  376.   End; { TestNumber }
  377.  
  378.  
  379. Procedure PrintPrimes;
  380.  
  381. { Reads primes from PrimeSem and prints them on screen }
  382.  
  383.   var buf    : ^BufferType;
  384.       ptr    : Pointer;
  385.  
  386.   Begin
  387.     Repeat
  388.        GetMsg(PrimeSem,ptr,stay);
  389.        buf:=ptr;
  390.  
  391.        Wait(CrtSem);
  392.        SelectWindow(3);
  393.        With WindowTable(.3.) Do
  394.          GotoXY(Xsize-2,Ysize-2);
  395.        Writeln;
  396.        Write(buf^.number:7);
  397.        Signal(CrtSem);
  398.  
  399.        PutMsg(BufferSem2,ptr);
  400.     Until
  401.       false;
  402.   End; { PrintPrimes }
  403.  
  404.  
  405. Procedure jabberwocky;
  406.  
  407. { Reads the Poem Jabberwocky from disk and prints it on the screen. }
  408.  
  409. var JabFile : text;
  410.     line    : String;
  411.  
  412. Begin
  413.   wait(DosSem);
  414.   Assign(JabFile,'JABWOCK.DAT');
  415.   Reset(JabFile);
  416.   signal(DosSem);
  417.  
  418.   While not eof(JabFile) Do
  419.   Begin
  420.     Wait(DosSem);
  421.     Readln(Jabfile,line);
  422.     Signal(DosSem);
  423.  
  424.     Wait(CrtSem);
  425.     SelectWindow(7);
  426.     With WindowTable(.7.) Do
  427.       GotoXY(Xsize-2,Ysize-2);
  428.     Writeln;
  429.     Write(' ',line);
  430.     Signal(CrtSem);
  431.     Delay(1);
  432.   End;
  433.  
  434.   Wait(DosSem);
  435.   Close(JabFile);
  436.   Signal(DosSem);
  437.  
  438.   Die;
  439.  
  440. End; { Jabberwocky }
  441.  
  442.  
  443.  
  444. Procedure control;
  445.  
  446. { Controls multiprogram. Spawns sub-processes }
  447.  
  448.  
  449. var buf : ^BufferType;
  450.     ptr : Pointer;
  451.     i   : Integer;
  452.     c   : Char;
  453.  
  454.  
  455.  
  456.    Procedure pause;
  457.  
  458.    { Waits for a keystroke }
  459.  
  460.    var keystroke : Boolean;
  461.  
  462.    Begin
  463.      While not KeyPressed Do
  464.      Begin
  465.        Wait(KbdSem);
  466.        Signal(KbdSem);
  467.      End;
  468.  
  469.      Wait(KbdSem);
  470.      c:=ReadKey;
  471.      Signal(KbdSem);
  472.    End; { pause }
  473.  
  474.  
  475. Begin
  476.   MakeWindow( 5,18,45,7,' Multi-Program Demo ');
  477.  
  478.   Wait(CrtSem);
  479.   SelectWindow(1);
  480.   ClrScr;
  481.   Writeln(' Welcome to the demonstration of the');
  482.   Writeln(' multi-program unit. This window is a');
  483.   Writeln(' process under the multi-program. In');
  484.   Writeln(' a minute we''ll add some other processes.');
  485.   Write  (' Hit any key to continue.');
  486.   Signal(CrtSem);
  487.  
  488.   pause;
  489.  
  490.   Wait(CrtSem);
  491.   MakeWindow( 5, 2,18,5,' Numbers ');
  492.   MakeWindow(51, 2,12,6,' Primes ');
  493.   MakeWindow(27, 2,18,4,' Test_1 ');
  494.   MakeWindow(27, 7,18,4,' Test_2 ');
  495.   MakeWindow(27,12,18,4,' Test_3 ');
  496.  
  497.   { Send window-numbers to test-processes }
  498.   For i:=4 to 6 Do
  499.   Begin
  500.     GetMsg(BufferSem1,ptr,stay);
  501.     buf:=ptr;
  502.     buf^.number:=i;
  503.     PutMsg(WindowSem,ptr);
  504.   End;
  505.  
  506.   CreateProcess(@PrintPrimes,2000,proc2);
  507.   CreateProcess(@TestNumber,2000,proc3);
  508.   CreateProcess(@TestNumber,2000,proc4);
  509.   CreateProcess(@TestNumber,2000,proc5);
  510.   CreateProcess(@Numbers,2000,proc6);
  511.  
  512.   SelectWindow(1);
  513.   ClrScr;
  514.   Writeln(' First we''ll start a group of processes');
  515.   Writeln(' which calculate prime numbers.');
  516.   Writeln(' The processes communicate via message');
  517.   Writeln(' semaphores.');
  518.   Write  (' Hit any key to continue.');
  519.   Signal(CrtSem);
  520.  
  521.   pause;
  522.  
  523.   Wait(CrtSem);
  524.   SelectWindow(1);
  525.   ClrScr;
  526.   Writeln(' The process ''numbers'' generates numbers');
  527.   Writeln(' to be tested for prime-ness and sends');
  528.   Writeln(' them to a group of test-processes which');
  529.   Writeln(' test whether they are primes or not.');
  530.   Write  (' Hit any key to continue.');
  531.   Signal(CrtSem);
  532.  
  533.   pause;
  534.  
  535.   Wait(CrtSem);
  536.   SelectWindow(1);
  537.   ClrScr;
  538.   Writeln(' If they find a prime number, it is sent');
  539.   Writeln(' to the process ''Primes'' which will print');
  540.   Writeln(' it on the screen.');
  541.   Writeln;
  542.   Write  (' Hit any key to continue.');
  543.   Signal(CrtSem);
  544.  
  545.   pause;
  546.  
  547.   Wait(CrtSem);
  548.   MakeWindow(53,12,28,11,' Jabberwocky ');
  549.  
  550.   CreateProcess(@Jabberwocky,2000,proc7);
  551.  
  552.   SelectWindow(1);
  553.   ClrScr;
  554.   Writeln(' Next we''ll start a process which will');
  555.   Writeln(' read the poem Jabberwocky by Lewis Carrol');
  556.   Writeln(' from disk and print it on the screen');
  557.   Writeln;
  558.   Write  (' Hit any key to continue.');
  559.   Signal(CrtSem);
  560.  
  561.   pause;
  562.  
  563.   CreateProcess(@ball,2000,proc8);
  564.  
  565.   Wait(CrtSem);
  566.   SelectWindow(1);
  567.   ClrScr;
  568.   Writeln(' Now we''ll start a process which');
  569.   Writeln(' will bounce a ball around the screen. ');
  570.   Writeln(' There are now eight processes in the ');
  571.   Writeln(' multiprogram.');
  572.   Write  (' Hit any key to continue.');
  573.   Signal(CrtSem);
  574.  
  575.   pause;
  576.  
  577.   Wait(CrtSem);
  578.   SelectWindow(1);
  579.   ClrScr;
  580.   Writeln(' Finally we''ll commit a minor atrocity:');
  581.   Writeln(' killing one of the test-processes.');
  582.   Writeln;
  583.   Writeln;
  584.   Write  (' Hit any key to end program.');
  585.   Signal(CrtSem);
  586.  
  587.   { Send a negative number (= death sentence) to one of the test processes. }
  588.   GetMsg(BufferSem1,ptr,stay);
  589.   buf:=ptr;
  590.   buf^.number:=-1;
  591.   PutMsg(NumberSem,ptr);
  592.  
  593.   pause;
  594.  
  595.   Wait(DosSem);
  596.   Wait(CrtSem);
  597.   Wait(KbdSem);
  598.   stopmulti;
  599.  
  600. End; { Control }
  601.  
  602.  
  603. Begin { Main }
  604.   ClrScr;
  605.   NoWindows:=0;
  606.   SetCursor($2000);
  607.  
  608.   { Initalize screen table }
  609.   For i:=1 to 80 Do
  610.     For j:=1 to 25 Do screen(.i,j.):=free;
  611.   For i:=0 to 81 Do
  612.   Begin
  613.     screen(.i, 0.):=used;
  614.     screen(.i,25.):=used;
  615.   End;
  616.   For j:=1 to 25 Do
  617.   Begin
  618.     screen(. 0,j.):=used;
  619.     screen(.81,j.):=used;
  620.   End;
  621.  
  622.   { Initalize semaphores }
  623.   InitSem(DosSem);
  624.   InitSem(CrtSem);
  625.   InitSem(KbdSem);
  626.   InitMsgSem(BufferSem1);
  627.   InitMsgSem(BufferSem2);
  628.   InitMsgSem(WindowSem);
  629.   InitMsgSem(NumberSem);
  630.   InitMsgSem(PrimeSem);
  631.   InitMsgSem(BallSem);
  632.  
  633.   { Mark various ressources as 'free' }
  634.   Signal(DosSem);
  635.   Signal(CrtSem);
  636.   Signal(KbdSem);
  637.  
  638.   { Generate buffer-pools }
  639.   For i:=1 to 10 Do
  640.   Begin
  641.     new(buf);
  642.     ptr:=buf;
  643.     PutMsg(BufferSem1,ptr);
  644.     new(buf);
  645.     ptr:=buf;
  646.     PutMsg(BufferSem2,ptr);
  647.   End;
  648.  
  649.   CreateProcess(@control,2000,proc1);
  650.  
  651.   StartMulti(Timer);
  652.  
  653.   SetCursor($607);
  654. End.