home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / lan / spy / source / multi.doc next >
Text File  |  1989-10-03  |  9KB  |  193 lines

  1. { MULT.PAS : Non-Preemptive multitasking for Turbo Pascal V5.x.
  2.   This unit is not intended for programs that do I/O with the keyboard and
  3.   screen.  Screen output from different tasks will be intermixed; Read, ReadLn,
  4.   or ReadKey will hang all tasks until the completion of the input operation.
  5.   For full device support (keyboard, mouse, screen) with windows, use
  6.   MULTIWIN.PAS with WINDOW.PAS available from the author, with documentation
  7.   after 11-1-89.
  8.  
  9.   Remember, this is NON-Preemptive multitasking - you must call WAIT (see
  10.   below) to share the CPU.  The mainline task should be terminated with a
  11.   call to STOP (see below).  If the mainline is allowed to fall through and
  12.   MultiExitProc is not installed, the entire program will stop. }
  13.  
  14. { NOTE: Tasks may use the numeric coprocessor (real or emulated) and overlays
  15.   freely.  The IdleRoutine should not use the real 8087 or overlays, but may
  16.   use 8087 emulation.  An event handler must conform to the restrictions of
  17.   its _caller_.  For example, an event handler which is called from another
  18.   task has no restrictions, but an event handler called from the IdleRoutine
  19.   mustn't use overlays or the 8087.  In addition, an event handler must never
  20.   call WAIT, even indirectly.  Interrupt handlers which may be entered
  21.   asynchronously are, as usual, forbidden to use much of anything except as
  22.   noted below.  Overlay support was implemented for TP 5.0 and 5.5 and may not
  23.   work on any other release. }
  24.  
  25. { Copyright 1989 by: Edwin T. Floyd
  26.   All rights reserved
  27.   Non-commercial use permitted.
  28.  
  29.   Author: Edwin T. Floyd [76067,747]
  30.           #9 Adams Park Court
  31.           Columbus, GA 31909
  32.           (404) 322-0076 }
  33.  
  34. {$A+,B-,D-,E-,F+,I-,L-,N-,O-,R-,S-,V+}
  35. Unit MULTI;
  36. Interface
  37.  
  38. Const
  39.   MaxTasks = 32;                  { Maximum number of active tasks }
  40.   MaxResources = 8;               { Maximum number of resource queues }
  41.   MaxOverlays = 20;               { Maximum number of overlay units supported }
  42.   WaitStackSize = 2048;           { Size in bytes of wait-dispatch stack }
  43.   MainName = 'MAINLINE';          { Name of mainline task }
  44.   Forever = -1;                   { Wait time for unending wait }
  45.  
  46. Type
  47.   TaskType = 0..MaxTasks;
  48.   ResourceType = 1..MaxResources;
  49.   EventMessageType = (MsgStop, MsgKeystroke, MsgBreak, MsgMouse, MsgUser);
  50.   { MULTI only implements MsgStop }
  51.   DispatchHookType = (HookInit, HookIn, HookOut, HookStop, HookWake);
  52.   LockHookType = (HookLock, HookUnlock, HookLockNext);
  53.   EventMessage =
  54.     Record
  55.       MsgType : EventMessageType; { Event type }
  56.       MsgFlag : Byte;             { User message subtype }
  57.       MsgLen : Word;              { Length of message data }
  58.       MsgData : Pointer;          { Pointer to message data }
  59.     End;
  60.   SpawnRoutineType = Procedure(Param : Pointer);
  61.   EventRoutineType = Procedure(Task : TaskType; Var Event : EventMessage;
  62.                                Param : Pointer);
  63.   IdleRoutineType = Procedure(Timeout : LongInt);
  64.   HookRoutineType = Procedure(Task : TaskType; Entry : DispatchHookType);
  65.   LockRoutineType = Procedure(Var Task : TaskType; Res : ResourceType;
  66.                               Entry : LockHookType);
  67.   TaskNameType = String[8];
  68.  
  69. Var
  70.   MultiExitChain : Pointer;       { ExitProc to restore after MultiExitProc }
  71.   DispatchHook : HookRoutineType; { Dispatch hook for add-ons (i.e. MultiWin) }
  72.   LockHook : LockRoutineType;     { Lock hook for add-ons (i.e. MultiWin) }
  73.   IdleRoutine : IdleRoutineType;  { Routine to call when waiting }
  74.   MRCTaskId : TaskType;           { Task Id of most recently created task }
  75.  
  76. { Unless otherwise indicated in a "**:" note, any routine below may be called
  77.   from an interrupt handler or an event handler.   }
  78.  
  79. Procedure Spawn(Routine : SpawnRoutineType; Param : Pointer; StkSize : Word;
  80.                 Name : TaskNameType);
  81.   { Create a new task. If successful, new task Identifier is placed in
  82.     MRCTaskId. Otherwise, MRCTaskId is set to zero.  **: Spawn calls GetMem to
  83.     allocate a control block and stack on the Heap.  Do NOT call Spawn from an
  84.     INTERRUPT handler! }
  85.  
  86. Function TaskExists(Task : TaskType) : Boolean;
  87.   { Returns TRUE if Task is active. }
  88.  
  89. Function TaskName(Task : TaskType) : TaskNameType;
  90.   { Returns the name assigned to Task }
  91.  
  92. Function TaskParent(Task : TaskType) : TaskType;
  93.   { Returns the TaskId of the task which spawned a task }
  94.  
  95. Procedure Adopt(Task, NewParent : TaskType);
  96.   { Set the parent of a task (the parent receives a stop message when the
  97.     task terminates). }
  98.  
  99. Function FindTask(Name : TaskNameType) : TaskType;
  100.   { Returns the TaskId of the named task if it exists, returns 0 otherwise }
  101.  
  102. Function TaskCount : Byte;
  103.   { Returns number of active tasks. }
  104.  
  105. Function MyTaskId : TaskType;
  106.   { Returns identifier of currently executing task. **: This returns 0 if
  107.     called from an interrupt or event handler while all tasks are waiting.
  108.     This always returns 0 if called from the IdleRoutine.  MyTaskId = 0
  109.     disables some of the following procedures (see notes below). }
  110.  
  111. Procedure Wait(Time : LongInt);
  112.   { Wait until Wake is called for this task, or Time (in sec/100)
  113.     has elapsed (if Time >= 0). **: DO NOT CALL FROM INTERRUPT or
  114.     EVENT HANDLER! }
  115.  
  116. Procedure Wake(Task : TaskType);
  117.   { Awaken a waiting task before it's timeout has expired. }
  118.  
  119. Procedure StopTask(Task : TaskType);
  120.   { Stop task, release its resources.  **: This is safe to call from an
  121.     Interrupt or Event handler ONLY if Task <> MyTaskId! }
  122.  
  123. Procedure Stop;
  124.   { Stop current task, equivalent to StopTask(MyTaskId). **: DO NOT CALL FROM
  125.     INTERRUPT or EVENT HANDLER! }
  126.  
  127. Procedure StopAll(ExitCode : Word);
  128.   { Stop all tasks and exit. **: DO NOT CALL FROM INTERRUPT or EVENT HANDLER! }
  129.  
  130. Procedure FreezeTask(Task : TaskType);
  131.   { Freeze a task. (you can't freeze MyTaskId) }
  132.  
  133. Procedure ThawTask(Task : TaskType);
  134.   { Un-freeze a frozen task }
  135.  
  136. Procedure GetExitProc(Var Routine : SpawnRoutineType; Var Param : Pointer);
  137.   { Returns the entry point and parameter of the exit routine for the current
  138.     task.  **: Won't work if MyTaskId = 0. }
  139.  
  140. Procedure SetExitProc(Routine : SpawnRoutineType; Param : Pointer);
  141.   { Establish an exit routine for current task.  Note: This exit routine
  142.     is activated upon termination of the current task only.  See MultiExitProc
  143.     below for information on a system exit routine. **: Won't work if
  144.     MyTaskId = 0. }
  145.  
  146. Procedure GetEventProc(Var Routine : EventRoutineType; Var Param : Pointer);
  147.   { Returns the entry point and param of the event handler for the current
  148.     task.  A task should call this before calling SetEventProc and save the
  149.     entry point and param of the previous event handler so that the new event
  150.     handler may relay non-user messages. **: Won't work if MyTaskId = 0. }
  151.  
  152. Procedure SetEventProc(Routine : EventRoutineType; Param : Pointer);
  153.   { Establish an event handler routine for the current task.  Note: User event
  154.     handlers should relay all messages except MsgType = MsgUser to the previous
  155.     event handler. **: Won't work if MyTaskId = 0.  }
  156.  
  157. Procedure CallEventProc(Task : TaskType; Var Event : EventMessage);
  158.   { Call the event routine associated with the indicated task.  Note:
  159.     EventMessage.MsgType MsgStop..MsgMouse are reserved system messages; task
  160.     initiated messages should be MsgType = MsgUser. }
  161.  
  162. Function Lock(Res : ResourceType; Timeout : LongInt) : Boolean;
  163.   { Reserve a serial resource.  **: Lock may call Wait, so DO NOT CALL FROM
  164.     INTERRUPT or EVENT HANDLER! }
  165.  
  166. Procedure Unlock(Res : ResourceType);
  167.   { Release a serial resource.  **: Does nothing if MyTaskId = 0. }
  168.  
  169. Function Preempt(Res : ResourceType; Task : TaskType) : TaskType;
  170.   { Unconditionally reserve a serial resource for the indicated task.  Returns
  171.     the TaskId of the previous owner. }
  172.  
  173. Function ResourceOwner(Res : ResourceType) : TaskType;
  174.   { Returns the TaskId of the current owner of the resource.  Returns 0 (zero)
  175.     if no task has locked the resource. }
  176.  
  177. Function TimeNow : LongInt;
  178.   { Returns the time in hundredths of a second since the beginning of the day
  179.     in which the first call to TimeNow was made.  TimeNow is actually only as
  180.     accurate as the BIOS clock tick which occurs about once each 5.5 hundredths
  181.     of a second.  This function is used by the dispatcher. }
  182.  
  183. Procedure MultiExitProc;
  184.   { Exit proc which terminates the current task with an error message but
  185.     allows the remaining tasks to continue.  Do not call this procedure
  186.     directly.  Do this to activate MultiExitProc:
  187.  
  188.     MultiExitChain := ExitProc;
  189.     ExitProc := @MultiExitProc; }
  190.  
  191. Implementation
  192. Uses Dos;
  193.