Contributor: HEGEL UDO 
Unit Multi;
{--------------------------------------------------------------------------------}
{ }
{ Hilfsfunktionen zur quasi-Multitaskingverarbeitung unter Turbo Pascal }
{ }
{ (c) 1994 by Hegel Udo }
{ }
{--------------------------------------------------------------------------------}
Interface
{--------------------------------------------------------------------------------}
Type
 StartProc = Procedure;
{--------------------------------------------------------------------------------}
Procedure AddTask (Start : StartProc;StackSize : Word);
Procedure Transfer;
{--------------------------------------------------------------------------------}
Implementation
{--------------------------------------------------------------------------------}
Uses
 Dos;
{--------------------------------------------------------------------------------}
Type
 TaskPtr = ^TaskRec;
 TaskRec = Record
 StackSize : Word;
 Stack : Pointer;
 SPSave : Word;
 SSSave : Word;
 BPSave : Word;
 Next : TaskPtr;
 end;
{--------------------------------------------------------------------------------}
Const
 MinStack = 1024;
 MaxStack = 32768;
{--------------------------------------------------------------------------------}
Var
 Tasks : TaskPtr;
 AktTask : TaskPtr;
 OldExit : Pointer;
{--------------------------------------------------------------------------------}
Procedure AddTask (Start : StartProc;StackSize : Word);
Type
 OS = Record
 O,S : Word;
 end;
Var
 W : ^TaskPtr;
 SS : Word;
 SP : Word;
begin
 W := @Tasks;
 While Assigned (W^) do W := @W^^.Next;
 New (W^);
 if StackSize < MinStack then StackSize := MinStack; if StackSize> MaxStack then StackSize := MaxStack;
 W^^.StackSize := StackSize;
 GetMem (W^^.Stack,StackSize);
 SS := OS(W^^.Stack).S;
 SP := OS(W^^.Stack).O+StackSize-4;
 Move (Start,Ptr(SS,SP)^,4);
 W^^.SPSave := SP;
 W^^.SSSave := SS;
 W^^.BPSave := W^^.SPSave;
 W^^.Next := NIL;
end;
{--------------------------------------------------------------------------------}
Procedure Transfer; Assembler;
Asm
 LES SI,AktTask { Alter Status sichern }
 MOV ES:[SI].TaskRec.SPSave,SP
 MOV ES:[SI].TaskRec.SSSave,SS
 MOV ES:[SI].TaskRec.BPSave,BP
 MOV AX,Word Ptr ES:[SI].TaskRec.Next { Neue Task bestimmen }
 OR AX,Word Ptr ES:[SI].TaskRec.Next+2
 JE @InitNew
 LES SI,ES:[SI].TaskRec.Next
 JMP @DoJob
@InitNew:
 LES SI,Tasks
@DoJob:
 MOV Word Ptr AktTask,SI { Neue Task Sichern }
 MOV Word Ptr AktTask+2,ES
 CLI { Status wieder hertstellen }
 MOV SP,ES:[SI].TaskRec.SPSave
 MOV SS,ES:[SI].TaskRec.SSSave
 STI
 MOV BP,ES:[SI].TaskRec.BPSave
end;
{--------------------------------------------------------------------------------}
BEGIN
 New (Tasks); { Hauptprogramm als Task anmelden }
 Tasks^.StackSize := 0;
 Tasks^.Stack := NIL;
 Tasks^.Next := NIL;
 AktTask := Tasks;
END.
{ -------------------------- DEMO PROGRAM ---------------------- }
Program Multi_Demo;
Uses
 DOS, Crt, Multi;
TYPE
 ScreenState = (free, used); { Is screen position free? }
 WindowType = Record { Window descriptor }
 X,
 Y,
 Xsize,
 Ysize : Integer;
 End;
var screen : Array(.0..81,0..26.) of ScreenState;
 WindowTable : Array(.1..20.) of WindowType;
 i,j, { Index variables }
 NoWindows : Integer; { No. of windows on screen }
Procedure MakeWindow(X, Y, Xsize, Ysize: Integer; Heading: String);
{ Reserves screenspace for window and draws border around it }
 const NEcorner = #187; { Characters for double-line border }
 SEcorner = #188;
 SWcorner = #200;
 NWcorner = #201;
 Hor = #205;
 Vert = #186;
 var i,j : Integer;
 Begin
 Window(1,1,80,25);
 { Reserve screen space }
 For i:=X to X+Xsize-1 Do
 For j:=Y to Y+Ysize-1 Do screen(.i,j.):=used;
 { Draw border - sides }
 i:=X;
 For j:=Y+1 to Y+Ysize-2 Do
 Begin
 GotoXY(i,j);
 Write(Vert);
 End;
 i:=X+Xsize-1;
 For j:=Y+1 to Y+Ysize-2 Do
 Begin
 GotoXY(i,j);
 Write(Vert);
 End;
 j:=Y;
 For i:=X+1 to X+Xsize-2 Do
 Begin
 GotoXY(i,j);
 Write(Hor);
 End;
 j:=Y+Ysize-1;
 For i:=X+1 to X+Xsize-2 Do
 Begin
 GotoXY(i,j);
 Write(Hor);
 End;
 { Draw border - corners }
 GotoXY(X,Y);
 Write(NWcorner);
 GotoXY(X+Xsize-1,Y);
 Write(NEcorner);
 GotoXY(X+Xsize-1,Y+Ysize-1);
 Write(SEcorner);
 GotoXY(X,Y+Ysize-1);
 Write(SWcorner);
 { Make Heading }
 GotoXY(X+(Xsize-Length(Heading)) div 2,Y);
 Write(heading);
 { Save in table }
 NoWindows:=NoWindows+1;
 WindowTable(.NoWindows.).X:=X;
 WindowTable(.NoWindows.).Y:=Y;
 WindowTable(.NoWindows.).Xsize:=Xsize;
 WindowTable(.NoWindows.).Ysize:=Ysize;
 End; { MakeWindow }
Procedure SelectWindow(i : Integer);
 { Specifies which window will receive subsequent output }
 Begin
 With WindowTable(.i.) Do
 Begin
 Window(X+1,Y+1,X+Xsize-2,Y+Ysize-2);
 End;
 End; { SelectWindow }
Procedure RemoveWindow(n: Integer);
 { Removes window number n }
 var i,j : Integer;
 Begin
 SelectWindow(n);
 With WindowTable(.n.) Do
 Begin
 Window(X,Y,X+Xsize,Y+Ysize);
 For i:=X to X+Xsize Do
 For j:=Y to Y+Ysize Do screen(.i,j.):=free;
 End; { With }
 ClrScr;
 End; { SelectWindow }
Procedure Task1;Far;
VAR
 SR : SearchRec;
begin
 MakeWindow(27, 2,18,4,' Sub Task 1 ');
 REPEAT
 FINDFIRST('*.*',anyfile,SR);
 WHILE DOSERROR = 0 DO
 BEGIN
 Transfer;
 SelectWindow(2);
 WriteLn(SR.Name : 12);
 FINDNEXT(SR);
 Delay(10);
 END;
 UNTIL FALSE;
end;
Procedure Task2;Far;
VAR
 SR : SearchRec;
begin
 MakeWindow(27, 7,18,4,' Sub Task 2 ');
 REPEAT
 FINDFIRST('\TURBO\TP\*.*',anyfile,SR);
 WHILE DOSERROR = 0 DO
 BEGIN
 Transfer;
 SelectWindow(3);
 WriteLn(SR.Name : 12);
 FINDNEXT(SR);
 Delay(10);
 END;
 UNTIL FALSE;
end;
Procedure Task3;Far;
VAR
 SR : SearchRec;
begin
 MakeWindow(27,12,18,4,' Sub Task 3 ');
 REPEAT
 FINDFIRST('\TURBO\*.*',anyfile,SR);
 WHILE DOSERROR = 0 DO
 BEGIN
 Transfer;
 SelectWindow(4);
 WriteLn(SR.Name : 12);
 FINDNEXT(SR);
 Delay(10);
 END;
 UNTIL FALSE;
end;
Procedure Task4;Far;
VAR
 SR : SearchRec;
begin
 MakeWindow(27,17,18,4,' Sub Task 4 ');
 REPEAT
 FINDFIRST('\*.*',anyfile,SR);
 WHILE DOSERROR = 0 DO
 BEGIN
 Transfer;
 SelectWindow(5);
 WriteLn(SR.Name : 12);
 FINDNEXT(SR);
 Delay(10);
 END;
 UNTIL FALSE;
end;
BEGIN
 ClrScr;
 MakeWindow( 5,21,75,4,' Multi-Program Demo ');
 SelectWindow(1);
 WriteLn(' This is the MAIN task window and we will start 4 others too');
 AddTask (Task1,8192);
 AddTask (Task2,8192);
 AddTask (Task3,8192);
 AddTask (Task4,8192);
 REPEAT
 Transfer;
 UNTIL KEYPRESSED;
END.
 

AltStyle によって変換されたページ (->オリジナル) /