home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / euphoria / sched.e < prev    next >
Text File  |  1994-01-08  |  4KB  |  121 lines

  1. -- sched.e
  2. -- Task Scheduler
  3.  
  4. -- This is perhaps the most interesting source file since it shows a
  5. -- simple technique of task scheduling that could be used in any action 
  6. -- game or simulation program. 
  7.  
  8. -- We have implemented a form of cooperative multitasking to manage 10 
  9. -- independent tasks. There is a task that moves the Euphoria, another task 
  10. -- that checks the keyboard for input, a task that makes enemy ships fire, 
  11. -- another that counts down the damage report, etc. The sequence "tcb" records
  12. -- the time at which each task wants to be activated next. When the time comes 
  13. -- to run a given task, the scheduler will return to the main program, telling
  14. -- it which task to run. When the task is finished it can tell the scheduler 
  15. -- when it would like to be activated next. 
  16.  
  17. -- For example, the task that moves the Euphoria will ask to be activated 
  18. -- again in 20 seconds if the Euphoria is moving at warp 1, or much less at 
  19. -- higher warps. The keyboard checking task is activated very frequently, but 
  20. -- usually returns quickly (no key pressed). 
  21.  
  22. -- Some tasks require very precise activation times to make things look 
  23. -- realistic, e.g. Euphoria moving at warp 5. Others do not, for example the 
  24. -- BASIC TRUCE/HOSTILE/CLOAKING task which is activated after a lengthy and 
  25. -- random amount of time. In recognition of this we have the "eat" (early 
  26. -- activation tolerance) variable. After choosing the next task to run, and 
  27. -- before entering into a delay loop to wait for the activation time to come,
  28. -- the scheduler will check the eat to see if it can activate the task a bit
  29. -- early. This will get this task out of the way a bit earlier and
  30. -- reduce the chance of a timing conflict with the next task.
  31.  
  32. -- Having said all this, the code is actually quite simple:
  33.  
  34. global constant HUGE_TIME = 1e30
  35. global constant INACTIVE = 0
  36.  
  37. global procedure sched(task t, positive_atom wait)
  38. -- schedule a task to be reactivated in wait seconds
  39.  
  40.     if wait = INACTIVE then
  41.     -- deactivate
  42.     tcb[t] = HUGE_TIME
  43.     else
  44.     -- activate in wait seconds from now
  45.     tcb[t] = time() + wait
  46.     end if
  47. end procedure
  48.  
  49.  
  50. global function next_task()
  51. -- choose the next task to be executed
  52.  
  53.     positive_atom mintime
  54.     task mintask
  55.  
  56.     -- find task with minimum time
  57.     mintime = HUGE_TIME
  58.     for i = 1 to NTASKS do
  59.     if tcb[i] < mintime then
  60.         mintask = i
  61.         mintime = tcb[i]
  62.     end if
  63.     end for
  64.  
  65.     -- subtract it's early-activation tolerance
  66.     tcb[mintask] = tcb[mintask] - eat[mintask]
  67.  
  68.     -- wait until it is time to activate it
  69.     while time() < tcb[mintask] do
  70.     end while
  71.  
  72.     return mintask
  73. end function
  74.  
  75.  
  76. -- below we have some code that lets us perform short accurate time delays
  77. -- with better resolution than the usual 18.2 ticks per second under MS-DOS
  78. constant sample_interval = 1.0
  79. atom sample_count
  80.  
  81. type reasonable_delay(atom x)
  82.     return x > 0 and x < 30
  83. end type
  84.  
  85. global procedure init_delay()
  86. -- since time() does not have fine enough
  87. -- resolution for small delays, we see how many for-loop iterations
  88. -- we can complete over a small sample period
  89.  
  90.     atom t
  91.  
  92.     t = time() + sample_interval
  93.     for i = 1 to 999999999 do
  94.     if time() < t then
  95.     else
  96.         sample_count = i
  97.         exit
  98.     end if
  99.     end for
  100. end procedure
  101.  
  102. global procedure delay(reasonable_delay t)
  103. -- delay for t seconds
  104.     atom stop
  105.     if t > sample_interval then
  106.     -- time() should be precise enough
  107.     stop = time() + t
  108.     while time() < stop do
  109.     end while
  110.     else
  111.     -- loop a certain number of times
  112.     stop = time() + sample_interval
  113.     for i = 1 to floor(t / sample_interval * sample_count) do
  114.         if time() < stop then
  115.         else
  116.         end if
  117.     end for
  118.     end if
  119. end procedure
  120.  
  121.