home *** CD-ROM | disk | FTP | other *** search
- {
- ════════════════════════════════════════════════════════════════════════════
-
- Visionix Process/Procedure/Thread "Multitasking" Unit (VMULTI)
- Version 0.6
- Copyright 1991,92,93 Visionix
- ALL RIGHTS RESERVED
-
-
- ────────────────────────────────────────────────────────────────────────────
-
- Revision history in reverse chronological order:
-
- Initials Date Comment
- ──────── ──────── ────────────────────────────────────────────────────────
-
- lpg 03/16/93 Added Source Documentation
-
- mep 02/11/93 Cleaned up code for beta release
-
- jrt 02/08/93 Sync with beta 0.12 release
-
- jrt 12/07/92 Sync with beta 0.11 release
-
- jrt 11/21/92 Sync with beta 0.08
-
- jrt 09/01/92 First logged revision.
-
- ════════════════════════════════════════════════════════════════════════════
- }
-
- (*-
-
- [TEXT]
-
- <Overview>
-
- VMultiu implements a simple, procedure based, non-preemptive multitasking
- facility.
-
- THIS UNIT IS INCOMPLETE!
-
- In the next release, it will also implement a cross-platform
- multi-thread facility, and the ability to work with DesqView, OS/2
- and Windows to evenly distribute time slices.
-
- <Interface>
- -*)
-
- Unit VMultiu;
-
- Interface
-
- Uses
-
- VTypesu,
- DOS;
-
- {────────────────────────────────────────────────────────────────────────────}
-
- Const
-
- VMS_New = 1;
- VMS_Do = 2;
- VMS_Dispose = 3;
-
- Type
-
- TMultiProc = Procedure( Status : BYTE; IData : Pointer );
-
- PMultiProcList = ^TMultiProcList;
-
- TMultiProcList = Record
-
- Proc : TMultiProc; { pointer to procedure }
- Interval : LONGINT; { interval between required processing }
- SPL : BYTE; { service processing level: }
- { 7=highest priority, 0 = lowest }
- Name : ST80; { process name }
- ID : Pointer; { process Instance Data }
- LastCall : LONGINT; { last call time }
- InProc : BOOLEAN; { already in procedure? }
-
- Next : PMultiProcList;
-
- END;
-
- TMachine = Record
-
- MultiProcListHead : PMultiProcList;
- MultiProcListCurr : PMultiProcList;
- MultiProcListTail : PMultiProcList;
-
- END;
-
- {────────────────────────────────────────────────────────────────────────────}
-
- Procedure VMultiProcNew( Prc : TMultiProc;
- Interval : LONGINT;
- SPL : BYTE;
- Name : TProcName;
- ID : POINTER;
- Var Error : WORD );
-
- Procedure VMultiProcDispose( Name : TProcName );
-
- Procedure VMultiProcSetSPL( Name : TProcName );
-
- Procedure VMultiThreadNew( Prc : Pointer;
- CallInterval : LONGINT;
- StayInterval : LONGINT;
- SPL : BYTE;
- Name : TProcName;
- StackSize : WORD;
- StackPtr : Pointer );
-
- Procedure VMultiThreadDispose( Name : TProcName );
-
- Procedure VMultiThreadSetSPL( Name : TProcName );
-
- Procedure VMultiDo( SPL : BYTE );
-
- Procedure VMultiSleep( Duration : WORD );
-
- Procedure VMultiCriticalBEGIN;
-
- Procedure VMultiCriticalEND;
-
- Procedure VMultiSetDVSPL( SPL : BYTE );
-
- Procedure VMultiSetWinSPL( SPL : BYTE );
-
- {────────────────────────────────────────────────────────────────────────────}
-
- Implementation
-
- Var
-
- M : TMachine;
-
- {────────────────────────────────────────────────────────────────────────────}
-
- Function GetLongintTime : Longint;
-
- Var
-
- H,M,S,S100 : WORD;
-
- BEGIN
-
- GetTime( H,M,S,S100 );
-
- GetLongintTime := ( Longint( H ) * 60 * 60 * 100 ) +
- ( Longint( M ) * 60 * 100 ) +
- ( Longint( S ) * 100 ) + S100;
-
- END; { GetLongintTime }
-
- {────────────────────────────────────────────────────────────────────────────}
-
- (*-
-
- [FUNCTION]
-
- Procedure VMultiProcNew( Prc : TMultiProc;
- Interval : LONGINT;
- SPL : BYTE;
- Name : TProcName;
- Var Error : WORD );
-
- [PARAMETERS]
-
- Prc Pointer to Called Procedure
- Interval Time between updates in MilliSeconds
- SPL Service Processing Level (7=Highest,0=Lowest)
- Name Name of Process Action
- Handle VAR Returned Multi-tasking Process ID Number
- Error VAR Returned Error Code (0=Success)
-
- [RETURNS]
-
- Function : None
- (VAR : [Handle] Multi-tasking Process ID Number)
- (VAR : [Error] Error Code)
-
- [DESCRIPTION]
-
- This procedure adds a new "multi-proc" to an internally stored list
- of "multi-procedures". Multi procedures are procedures that can be
- called non-premptively when other functions, procedures, units, etc
- call the VMultiDO function.
-
- Prc Pointer to Multi-Procedure.
-
- Interval Minimum wait between calls, in 100ths of a
- second.
-
- SPL System Priority Level. How "important"
- it is that this multi-proc gets called.
- 0 is most important, 10 is least.
-
- Name Name of the procedure.
-
- After the new multi-proc has been added to the list, the multi-proc
- will get called when other functions and routines call the VMultiDo
- function. VMultiDo will check to see if it has been longer than
- "interval" 100ths of a second since the multi proc has been called,
- and if that time has elapsed, it will call the procedure. This creates
- a simple mechanism to have procedures called in a non-premptive manner.
- All VisionTools libraries make calls to VMultiDo in the appropriate
- places (IE: when waiting for a key, when doing long operationg, etc.)
-
- TMultiProc = Procedure( Status : BYTE; IData : Pointer );
-
-
- When VMulti calls the new multi procedure, it will pass it one of
- three values in the Status byte:
-
- VMS_New = 1; { tells the multiproc this is the first call }
- VMS_Do = 2; { tells the multiproc it is a normal call }
- VMS_Dispose = 3; { tells the multiproc this is the last call }
-
-
-
-
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Procedure VMultiProcNew( Prc : TMultiProc;
- Interval : LONGINT;
- SPL : BYTE;
- Name : TProcName;
- ID : POINTER;
- Var Error : WORD );
-
- Var
-
- MPN : PMultiProcList;
-
- BEGIN
-
- With M Do
- BEGIN
-
- New( MPN );
-
- If MultiProcListHead = NIL Then
- BEGIN
-
- MultiProcListHead := MPN;
- MultiProcListCurr := MPN;
- MultiProcListTail := MPN;
-
- END; { If MultiProcListHead }
-
- MPN^.Proc := Prc;
- MPN^.Interval := Interval;
- MPN^.SPL := SPL;
- MPN^.Name := Name;
- MPN^.InProc := FALSE;
- MPN^.LastCall := 0;
- MPN^.ID := ID;
- MPN^.Next := MultiProcListHead;
-
- MultiProcListTail^.Next := MPN;
-
- MultiProcListTail := MPN;
-
- {--------------------}
- { Call the procedure }
- {--------------------}
-
- MPN^.Proc( VMS_New, MPN^.ID );
-
- END; { With M }
-
- END; { VMultiProcNew }
-
- {────────────────────────────────────────────────────────────────────────────}
-
- (*-
-
- [FUNCTION]
-
- Procedure VMultiProcDispose( Name : TProcName );
-
- [PARAMETERS]
-
- Name Name of Process to Remove from List
-
- [RETURNS]
-
- (None)
-
- [DESCRIPTION]
-
- Removes processes from the Multi-Tasking Processing list.
- Disposes of a previously allocated multi-proc.
-
- Name Name of the procedure to dispose of.
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Procedure VMultiProcDispose( Name : TProcName );
-
- BEGIN
-
- END; { VMultiProcDispose }
-
- {────────────────────────────────────────────────────────────────────────────}
-
- (*-
-
- [FUNCTION]
-
- Procedure VMultiProcSetSPL( Name : TProcName );
-
- [PARAMETERS]
-
- Name Name of Process to set the SPL Level on
-
- [RETURNS]
-
- (None)
-
- [DESCRIPTION]
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Procedure VMultiProcSetSPL( Name : TProcName );
-
- BEGIN
-
- END; { VMultiProcSetSPL }
-
- {────────────────────────────────────────────────────────────────────────────}
-
- (*-
-
- [FUNCTION]
-
- Procedure VMultiThreadNew( Prc : Pointer;
- CallInterval : LONGINT;
- StayInterval : LONGINT;
- SPL : BYTE;
- Name : TProcName;
- StackSize : WORD;
- StackPtr : Pointer );
-
- [PARAMETERS]
-
- Prc Pointer to New Thread Procedure
- CallInterval Time Between updates in Milliseconds
- StayInterval Amount of Processing Time to Spend at this Thread
- SPL Service Processing Level (7=Highest,0=Lowest)
- Name Name of Thread Processing Action
- StackSize Amount of Stack to Allocate to this Thread
- StackPtr Pointer to Allocated Stack
-
- [RETURNS]
-
- (None)
-
- [DESCRIPTION]
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Procedure VMultiThreadNew( Prc : Pointer;
- CallInterval : LONGINT;
- StayInterval : LONGINT;
- SPL : BYTE;
- Name : TProcName;
- StackSize : WORD;
- StackPtr : Pointer );
-
- BEGIN
-
- END; { VMultiThreadNew }
-
- {────────────────────────────────────────────────────────────────────────────}
-
- (*-
-
- [FUNCTION]
-
- Procedure VMultiThreadDispose( Name : TProcName );
-
- [PARAMETERS]
-
- Name Name of Thread Procedure to Dispose of
-
- [RETURNS]
-
- (None)
-
- [DESCRIPTION]
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Procedure VMultiThreadDispose( Name : TProcName );
-
- BEGIN
-
- END; { VMultiThreadDispose }
-
- {────────────────────────────────────────────────────────────────────────────}
-
- (*-
-
- [FUNCTION]
-
- Procedure VMultiThreadSetSPL( Name : TProcName );
-
- [PARAMETERS]
-
- Name Name of Thread Process to Set the SPL Level on
-
- [RETURNS]
-
- (None)
-
- [DESCRIPTION]
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Procedure VMultiThreadSetSPL( Name : TProcName );
-
- BEGIN
-
- END; { VMultiThreadSetSPL }
-
- {────────────────────────────────────────────────────────────────────────────}
-
- (*-
-
- [FUNCTION]
-
- Procedure VMultiDo( SPL : BYTE );
-
- [PARAMETERS]
-
- SPL Service Processing Level (7=Highest,0=Lowest)
-
- [RETURNS]
-
- (None)
-
- [DESCRIPTION]
-
- This is the key function called to update all multitasking functions
- that are equal to or greater than the submitted processing level.
- Allows multi-procs of a priority <= SPL to run.
-
- Calling this function with an SPL of Zero (0) allows ALL Processes
- to be executed. This is considered the Standard action.
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Procedure VMultiDo( SPL : BYTE );
-
- Var
-
- MPN : PMultiProcList;
- TimeNow : LONGINT;
- DidOne : BOOLEAN;
-
- BEGIN
-
- MPN := M.MultiProcListCurr;
-
- If MPN <> NIL Then
- BEGIN
-
- TimeNow := GetLongintTime;
-
- DidOne := FALSE;
-
- REPEAT
-
- If ( Not MPN^.InProc ) And
- ( MPN^.SPL >= SPL ) And
- ( TimeNow - MPN^.LastCall > MPN^.Interval ) Then
- BEGIN
-
- MPN^.InProc := TRUE;
- MPN^.Proc( VMS_Do, MPN^.ID );
- MPN^.InProc := FALSE;
- MPN^.LastCall := TimeNow;
- DidOne := TRUE;
-
- END; { If NOT MPN^InProc }
-
- MPN := MPN^.Next;
-
- UNTIL (DidOne) or ( MPN = M.MultiProcListCurr );
-
- M.MultiProcListCurr := M.MultiProcListCurr^.Next;
-
- END; { If MPN }
-
- END; { VMultiDo }
-
- {────────────────────────────────────────────────────────────────────────────}
-
- (*-
-
- [FUNCTION]
-
- Procedure VMultiSleep( Duration : WORD );
-
- [PARAMETERS]
-
- Duration Amount of Time to Sleep (in Milliseconds)
-
- [RETURNS]
-
- (None)
-
- [DESCRIPTION]
-
- Functional equivalent of TP Delay, however this one allows for all MT
- actions to continue during the pause.
-
- Sleeps for "duration" milliseconds, allowing multi-procs to run.
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Procedure VMultiSleep( Duration : WORD );
-
- Var
-
- TheTime : LONGINT;
- StartTime : LONGINT;
-
- BEGIN
-
- StartTime := GetLongintTime;
-
- Repeat
-
- VMultiDo( 0 );
-
- TheTime := GetLongintTime;
-
- Until TheTime > StartTime + Duration;
-
- END; { VMultiSleep }
-
- {────────────────────────────────────────────────────────────────────────────}
-
- (*-
-
- [FUNCTION]
-
- Procedure VMultiCriticalBEGIN;
-
- [PARAMETERS]
-
- (None)
-
- [RETURNS]
-
- (None)
-
- [DESCRIPTION]
-
- Begin a critical section. No multi-procs will run, interrupts will
- be disabled, windows ENTER CRITICAL SECTION will be will be called.
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Procedure VMultiCriticalBEGIN;
-
- BEGIN
-
- END; { VMultiCriticalBEGIN }
-
- {────────────────────────────────────────────────────────────────────────────}
-
- (*-
-
- [FUNCTION]
-
- Procedure VMultiCriticalEND;
-
- [PARAMETERS]
-
- (None)
-
- [RETURNS]
-
- (None)
-
- [DESCRIPTION]
-
- Ends a critical section. Multi-proc can run, interrupts will be
- enabled, windows EXIT CRITICAL SECTION will be called.
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Procedure VMultiCriticalEND;
-
- BEGIN
-
- END; { VMultiCriticalEND }
-
- {────────────────────────────────────────────────────────────────────────────}
-
- (*-
-
- [FUNCTION]
-
- Procedure VMultiSetDVSPL( SPL : BYTE );
-
- [PARAMETERS]
-
- SPL Service Processing Level (7=Highest,0=Lowest)
-
- [RETURNS]
-
- (None)
-
- [DESCRIPTION]
-
- Sets the System Priority Level for DesqView task switching.
- When VMultiDo is called with a priority >= this SPL,
- DesqView will be informed that another DV task should run.
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Procedure VMultiSetDVSPL( SPL : BYTE );
-
- BEGIN
-
- END; { VMultiSetDVSPL }
-
- {────────────────────────────────────────────────────────────────────────────}
-
- (*-
-
- [FUNCTION]
-
- Procedure VMultiSetWinSPL( SPL : BYTE );
-
- [PARAMETERS]
-
- SPL Service Processing Level (7=Highest,0=Lowest)
-
- [RETURNS]
-
- (None)
-
- [DESCRIPTION]
-
- Sets the System Priority Level for Windows task switching.
- When VMultiDo is called with a priority >= this SPL,
- windows will be informed that another windows task should run.
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Procedure VMultiSetWinSPL( SPL : BYTE );
-
- BEGIN
-
- END; { VMultiSetWinSPL }
-
- {────────────────────────────────────────────────────────────────────────────}
-
- (*-
-
- [FUNCTION]
-
- Procedure VMultiSetOS2SPL( SPL : BYTE );
-
- [PARAMETERS]
-
- SPL Service Processing Level (7=Highest,0=Lowest)
-
- [RETURNS]
-
- (None)
-
- [DESCRIPTION]
-
- Sets the System Priority Level for OS/2 task switching.
- When VMultiDo is called with a priority >= this SPL,
- Os/2 will be informed that another task should run.
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Procedure VMultiSetOS2SPL( SPL : BYTE );
-
- BEGIN
-
- END; { VMultiSetOS2SPL }
-
- {────────────────────────────────────────────────────────────────────────────}
- {────────────────────────────────────────────────────────────────────────────}
- {────────────────────────────────────────────────────────────────────────────}
-
- BEGIN
-
- M.MultiProcListHead := NIL;
- M.MultiProcListTail := NIL;
- M.MultiProcListCurr := NIL;
-
- END.
-