home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / programming / vista_1 / !Manual_manual_thread < prev    next >
Encoding:
Text File  |  1996-01-04  |  17.5 KB  |  458 lines

  1. <html>
  2. <title>Thread</title>
  3. <h1>Thread</h1>
  4.  
  5. <p>
  6. <a name="synopsis"></a>
  7. <h2>Synopsis</h2>
  8.  
  9. <pre>
  10.  
  11.       class Thread : public ThreadResource, virtual public DeferredDelete
  12.          {
  13.          enum State ;
  14.          public:
  15.             <a href="file:thread#ct">Thread</a>(char *name, int priority = THREAD_BASE_PRIORITY, int newstack = 1) ;
  16.             virtual <a href="file:thread#dt">~Thread</a>() ;
  17.             void <a href="file:thread#start">start</a>() ;
  18.             virtual void <a href="file:thread#run">run</a>() = 0 ;
  19.             virtual void <a href="file:thread#stop">stop</a>() ;
  20.             virtual void <a href="file:thread#resume">resume</a>() ;
  21.             virtual void <a href="file:thread#kill">kill</a>() ;
  22.             virtual void <a href="file:thread#sleep1">sleep</a> (int time) ;
  23.             virtual void <a href="file:thread#sleep2">sleep</a> (ThreadResource *, int pri = THREAD_BASE_PRIORITY) ;
  24.             virtual void <a href="file:thread#wakeup">wakeup</a> () ;
  25.             virtual void <a href="file:thread#write">write</a> (ThreadPipe *pipe, char *buffer, int nbytes) ;
  26.             virtual void <a href="file:thread#read">read</a> (ThreadPipe *pipe, char *buffer, int max, int &nbytes) ;
  27.             void <a href="file:thread#setpriority">setpriority</a> (int pri) ;
  28.             virtual int <a href="file:thread#resource_available">resource_available</a>() ;
  29.             virtual void <a href="file:thread#exit">exit</a> (int status = 0) ;
  30.             virtual void <a href="file:thread#yield">yield</a>() ;
  31.          public:
  32.             int <a href="file:thread#accumulated_cputime">accumulated_cputime</a> ;
  33.             char *<a href="file:thread#name">name</a> ;
  34.             int <a href="file:thread#exit_status">exit_status</a> ;
  35.          } ;
  36.  
  37. </pre>
  38.  
  39. <h2>Description</h2>
  40.  
  41. This class is a preemptive thread.  It behaves like a process in an
  42. operating system like UNIX.  All threads in the program execute
  43. (notionally) simulataneously.
  44. <p>
  45. The Task class creates and maintains a set of threads which process the
  46. events received by the task <b>(except the EREDRAW event which cannot
  47. be a thread)</b>.  It ensures that Wimp_Poll is called
  48. at the correct frequency by interrupting all running threads at the
  49. appropriate time.  It also shares the available CPU time among the
  50. running threads in a fair manner to ensure that all threads can
  51. run.
  52. <p>
  53. The user program may create its own threads by deriving a new class from
  54. the Thread class.  The Thread class provides a set of virtual functions
  55. which should be overridden by the derived class in order to replace or
  56. enhance the default functionality.
  57. <p>
  58. A thread is created by invoking the <a href="file:thread#ct">constructor</a>
  59.  (e.g. using the 'new'
  60. operator).  You must give the thread a name (may be "" if none is
  61. needed).  You may also specify a default <a href="file:thread#pri">priority</a>
  62.  for the thread.  Once created, the thread is idle until it is started by calling
  63. the <a href="file:thread#start">start()</a> function.  This function simply places the thread in
  64. a queue but does not run it right away.  When the <a href="file:thread#start">start()</a> function
  65. returns the thread is ready to run.
  66. <p>
  67. A thread starts running by calling its <a href="file:thread#run">run()</a>
  68.  function.  This pure
  69. virtual function must be provided by a derived class and is the
  70. main body of the thread.  When the thread is running it will be
  71. interrupted by the system in order to give other threads a chance
  72. at the CPU.  Threads are interrupted every centisecond, but it depends
  73. on the relative priority of the threads whether it gives up the
  74. CPU or not.
  75. <p>
  76. When the <a href="file:thread#run">run()</a> function returns, the thread is stopped and returns
  77. to idle state from where it may be rerun by calling the <a href="file:thread#start">start()</a>
  78. function again.
  79.  
  80. <p>
  81. <a name="pri"></a>
  82. <h3>Thread Scheduling</h3>
  83.  
  84. All threads run simultaneously.  Obviously this cannot really happen
  85. as there is only one processor, so the library shares the CPU
  86. among the running threads.  The threads are kept on a queue
  87. and when a thread is preempted, the system chooses another thread
  88. to run.  Which thread is chosen depends on the priorities of the
  89. threads in the queue.
  90. <p>
  91. A thread accumulates CPU time.  The priority of a thread is a function
  92. of the amount of time the thread has had on the CPU recently.  The system
  93. chooses the thread with the 'highest' priority.  When a thread is
  94. created, the constructor can be given a 'base priority' with which
  95. to run the thread.  This value is added to the priority calculations
  96. on a context switch to give the true thread priority.  
  97. <p>
  98. A thread priority is simply a number.  The lower the number the 'higher'
  99. the priority of the thread.  The priorities are recalculated for every
  100. thread on a 'context switch' and the new value is based on the
  101. previous priority and the recent CPU usage.  The base priority
  102. can be used to specify whether the thread gets more or less
  103. CPU time than other threads.  The priority values run from
  104. 0 to 120 with 0 being the highest, 120 the lowest and 60 the
  105. average.  A thread created with a base priotity less than 60
  106. is known as a 'high priority thread' and will, on average, get
  107. more CPU time than threads of a lower priority.
  108. <p>
  109. When a thread is running there will be occasions when it is known that
  110. there is nothing to do for a while.  Rather than entering a tight loop,
  111. the thread should <a href="file:thread#yield">yield</a> to another thread which may have something
  112. to do.  This allows more efficient use of the CPU.
  113.  
  114.  
  115. <h3>Thread Resources</h3>
  116.  
  117. Threads need to be able to communicate.  A thread may <a href="file:thread#sleep2">sleep</a> waiting 
  118. for a 'resource' to become available.  A 'ThreadResource' is a
  119. simple class which contains a single flag.  The flag is called
  120. 'available' and has a non zero value if the resource is available.
  121. When a thread wants to wait for a resource to become available, it
  122. called the function 'sleep'.  There are two versions of this
  123. function:
  124. <p>
  125. <ol>
  126. <li><a href="file:thread#sleep2">sleep</a> (ThreadResource *, int pri)
  127. <li><a href="file:thread#sleep1">sleep</a> (int time)
  128. </ol>
  129. <p>   
  130. The first version is the general purpose sleep function.  With it a thread
  131. may sleep until the given resource becomes available.  When a thread
  132. is sleeping it is not using any CPU time.  It is awoken by the
  133. system when a special thread called the 'ResourceThread' notices that
  134. the resource has become available.  The second parameter to the
  135. function is the priority at which the thread should awaken.  This allows
  136. threads to wake up with differing priorities to adjust the order in which
  137. they will run.
  138. <p>
  139. The second sleep function is really a specialisation of the general
  140. purpose function.  This function allows a thread to sleep for 
  141. a specified period of time (in centiseconds).  It makes use
  142. of a built in resource called a 'ThreadTimer'.  The time will
  143. not be totally accurate but could be a couple of centiseconds
  144. out depending on the number of threads running.
  145. <p>
  146. When a resource becomes available, all threads sleeping on the resource
  147. will wake up.  The highest priority thread (lowest priority number) will
  148. run first.  All threads, when sleeping for a shared resource MUST
  149. check to ensure that the resource is still available when they wake up.
  150. If they don't check this, the program will not work properly.
  151. <p>
  152. A look at the class definition for a <a href="file:thread#synposis">Thread</a> will show that the Thread
  153. class is a ThreadResource itself.  The resource becomes available
  154. when the thread terminates execution by returning from the 'run()'
  155. function or otherwise self terminates.  This allows other threads to 
  156. wait for another thread to finish.  The <a href="file:thread#exit">exit()</a> function allows
  157. a thread to exit and set an <a href="file:#threadexit_status">exit status</a> for another thread to
  158. pick up.
  159. <p>
  160. A number of resources have been predefined:
  161. <pre>
  162.  
  163.    1. ThreadTimer      - A resource which waits for a specified amount of
  164.                          time before becoming available
  165.    2. ThreadPipe       - A resource which allows threads to send data through
  166.                          a memory based controlled pipe.  Threads contain
  167.                          member functions to read from and write to pipes.
  168.                          If a thread attempts to write to or read from a pipe
  169.                          and the resource isn't available, the thread will
  170.                          sleep until the pipe clears or has data.
  171.    3. ThreadSemaphore  - This is simply a flag which can be set, cleared and
  172.                          read.  It should be used by threads to protect
  173.                          shared pieces of data from the 'lost update'
  174.                          problem.  If a thread wishes to update a piece
  175.                          of shared data it should sleep until a semaphore
  176.                          protecting it has become available.  When it awakes
  177.                          it should recheck the semaphore and sleep again
  178.                          in case another thread has got it first.  If it
  179.                          gains control of the data (by waking up, checking
  180.                          the semaphore and finding it is still available), it
  181.                          should make the semaphore unavailable by clearing it.
  182.                          The thread can then update the data and notify other
  183.                          threads by setting the semaphore.
  184.  
  185. </pre>
  186.  
  187.  
  188.  
  189. <h2>Members</h2>
  190.  
  191. The following are descriptions of the member functions available to users of
  192. Threads.  There are other internal functions and data which are not relevent
  193. here.
  194.  
  195. <p>
  196. <a name="ct"></a>
  197. <h3>Thread::Thread (char *name,
  198.                       int priority = THREAD_BASE_PRIORITY,
  199.                       int newstack = 1)</h3>
  200.                       
  201.  
  202. This constructor creates a new thread.  The thread is given a name (which may be "").
  203. The second parameter is the base priority at which the thread will run.  This is a
  204. value added to the actual thread priority.  Lower values mean higher priority with
  205. 60 being the mid point.  Threads of higher priotity will get more CPU time on
  206. average.  The last parameter is not relevent to this discussion and is just
  207. used internally.
  208.  
  209.  
  210. <p>
  211. <a name="dt"></a>
  212. <h3>Thread::~Thread()</h3>
  213.  
  214. This the the thread destructor.  It will stop the thread running and remove it from
  215. the system.  It must only be invoked (using the delete operator) by another thread.
  216.  
  217.  
  218. <p>
  219. <a name="start"></a>
  220. <h3>Thread::start()</h3>
  221.  
  222. This function starts a thread running.  It returns right away after queuing the thread
  223. to run.  The thread will not start for a period of time.
  224.  
  225.  
  226. <p>
  227. <a name="run"></a>
  228. <h3>Thread::run()</h3>
  229.  
  230. This is a pure virtual function that must be provided by a derived class.  It is the
  231. body of the thread and will be first thing called when the thread begins to
  232. run.  The thread will stop running when this function returns.  The function
  233. can do anything it likes as the system will ensure that other threads get
  234. a chance to run and Wimp_Poll is called appropriately.
  235.  
  236.  
  237. <p>
  238. <a name="stop"></a>
  239. <h3>Thread::stop()</h3>
  240.  
  241. This function temporarily suspends a running thread.  The thread will be taken
  242. out of the queue of running threads and will not use any CPU time.  The thread
  243. may be restarted by use of the the resume() function.  The function may
  244. be called by a thread for itself or for another thread.
  245.  
  246.  
  247. <p>
  248. <a name="resume"></a>
  249. <h3>Thread::resume()</h3>
  250.  
  251. This function causes a stopped thread to begin at the point it left off.  The thread
  252. must have been previously stopped by a call to the stop() function.
  253.  
  254.  
  255. <p>
  256. <a name="kill"></a>
  257. <h3>Thread::kill()</h3>
  258.  
  259. This function is used to stop a thread in its tracks.  The killed thread will
  260. stop immediately and cannot be resumed.  It can, however, be rerun by 
  261. calling the start() function.  A thread can kill itself or another thread.
  262.  
  263.  
  264. <p>
  265. <a name="sleep1"></a>
  266. <h3>Thread::sleep(int time)</h3>
  267.  
  268. This causes a thread to go to sleep for a period of time.  The period is
  269. specified in centiseconds and a thread can cause itself or any other
  270. thread to go to sleep.  It will awake at a set priority when the time
  271. expires.
  272.  
  273.  
  274. <p>
  275. <a name="sleep2"></a>
  276. <h3> Thread::sleep(ThreadResource *, int pri = THREAD_BASE_PRIORITY)</h3>
  277.  
  278. This causes a thread to sleep waiting for the given resource to become
  279. available.  The second parameter specifies the priority at which it
  280. will awaken.  This can be used to determine the order in which the
  281. threads run when awoken.
  282.  
  283.  
  284. <p>
  285. <a name="wakeup"></a>
  286. <h3> Thread::wakeup()</h3>
  287.  
  288. This causes a sleeping thread to wake up before the resource becomes
  289. available.  Obviously, a thread cannot wake itself up (it is not running),
  290. but a thread may wake any other thread up.  The thread awoken will 
  291. run at the priority at which it slept.
  292.  
  293.  
  294. <p>
  295. <a name="write"></a>
  296. <h3> Thread::write (ThreadPipe *pipe, char *buffer, int nbytes)</h3>
  297.  
  298. This writes data to the given pipe.  The thread will ensure that the
  299. pipe is available for writing before performing the write.  Another
  300. thread should pick up the data by using the 'read()' call.
  301.  
  302. The data is written to the pipe from the address passed in
  303. 'buffer' which is 'nbytes' long.  If the data is too big for
  304. the pipe, it will be split into chunks.  The function will return
  305. when all the data has been written to the pipe (but not
  306. necessarily picked up).
  307.  
  308.  
  309. <p>
  310. <a name="read"></a>
  311. <h3> Thread::read (ThreadPipe *pipe, char *buffer, int max, int &nbytes)</h3>
  312.  
  313. This is used to read from a given pipe.  Another thread must have written
  314. data to the pipe before a read can be performed.  The 'buffer' parameter
  315. specifies the address that the data will be read into.  'max' is the
  316. maximum size of the space available, and 'nbytes' will be set to the
  317. actual number of bytes read.
  318.  
  319.  
  320. <p>
  321. <a name="setpriority"></a>
  322. <h3> Thread::setpriority(int pri)</h3>
  323.  
  324. This is used to set the base priority of a thread.  Again, the lower the
  325. value the higher the priority.
  326.  
  327.  
  328. <p>
  329. <a name="resource_available"></a>
  330. <h3> Thread::resource_available()</h3>
  331.  
  332. This virtual function is called by the ResourceThread to check whether the
  333. resource for which a thread is sleeping has become available.  This may be
  334. used in the case where a single 'available' flag within the resource is
  335. insufficient.  For example, the ThreadPipe resource is either available
  336. for read or write, but never both.  The resource's 'available' flag
  337. indicates that there is data in the pipe (ie available for reading).  If
  338. a thread wants to write to the pipe, it must provide a 'resource_available'
  339. function which checks the pipe's availability for writing (the 'available'
  340. flag being set to 0).  The default behaviour of this function is
  341. to return the 'available' flag to the caller.
  342.  
  343.  
  344. <p>
  345. <a name="exit"></a>
  346. <h3> Thread::exit (int status = 0)</h3>
  347.  
  348. This function is used to cause a thread to exit.  It is simular to the 'kill'
  349. function except it allows an exit status to be set for picking up by
  350. another thread.
  351.  
  352.  
  353. <p>
  354. <a name="yield"></a>
  355. <h3> Thread::yield()</h3>
  356.  
  357. This function causes a thread to give up the processor in favour of another
  358. thread.  Obviously it can only be called to yield the currently running
  359. thread.  It makes for a better performing program if this function is
  360. used liberally when it is known there is no work for a thread to do.  There
  361. should be no need to tight loops.
  362.  
  363.  
  364. <p>
  365. <a name="accumulated_cputume"></a>
  366. <h3> Thread::accumulated_cputime</h3>
  367.  
  368. This variable holds the amount of time a thread has occupied in the CPU.
  369. It is the number of centiseconds for which the thread has actually been
  370. running.  This is different from the amount of real time since the thread
  371. was started as threads do not get the CPU to themselves.  It is not
  372. guaranteed to be accurate.
  373.  
  374.  
  375. <p>
  376. <a name="name"></a>
  377. <h3> Thread::name</h3>
  378.  
  379. This is the name of the thread.
  380.  
  381.  
  382. <p>
  383. <a name="exit_status"></a>
  384. <h3> Thread::exit_status</h3>
  385.  
  386. This is the value set by the 'exit()' function when a thread terminates.
  387. It may be used to check the termination status of another thread.
  388.  
  389. <p>
  390. <a name="example"></a>
  391. <h2>Example</h2>
  392.  
  393. This example shows how to create a simple thread.  Once running the thread
  394. will track the mouse and write the coordinates into an icon in a window
  395. passed in the constructor.  The window must have an icon 0 which must
  396. be indirected and long enough to hold the text.
  397. <pre>
  398.  
  399. //
  400. // class definition
  401. //
  402.  
  403. class MouseTracker : public Thread
  404.    {
  405.    public:
  406.       MouseTracker (Window *w) ;        // constructor
  407.       ~MouseTracker() ;                 // destructor
  408.       void run() ;                      // run function
  409.    private:
  410.       Window *window ;
  411.    } ;
  412.  
  413. //
  414. // member functions
  415. //
  416.  
  417. // constructor: creates a thread with name "Tracker" and high priority
  418.    
  419. MouseTracker::MouseTracker (Window *w)
  420.    : Thread ("Tracker", 55)            // priority = high
  421.    {
  422.    window = w ;                        // just set the variable
  423.    }
  424.  
  425. // destructor
  426.  
  427. MouseTracker::~MouseTracker()
  428.    {
  429.    }
  430.  
  431. //
  432. // main thread run function.  This just loops forever reading the
  433. // mouse position and printing into an icon
  434.  
  435. void MouseTracker::run()
  436.    {
  437.    _kernel_swi_regs r ;
  438.    _kernel_oserror *e ;
  439.    int block[5] ;
  440.    Icon *ic = new Icon (window, 0) ;                        // icon 0
  441.    window->do_open() ;                                      // open the window
  442.    for (;;)
  443.       {
  444.       r.r[1] = (int)block ;
  445.       if ((e = _kernel_swi (Wimp_GetPointerInfo, &r, &r)) != NULL)    // get pointer position
  446.          throw e ;
  447.       ic->print ("(%d, %d)",block[0],block[1]) ;         // print result
  448.       yield() ;                                         // yield to next thread
  449.       }
  450.    }
  451.  
  452.    
  453. </pre>
  454. This simple example shows how to create and run a thread.  Many of these 
  455. threads may be running at once.  The system will schedule between
  456. them.
  457.  
  458.