home *** CD-ROM | disk | FTP | other *** search
- <html>
- <title>Thread</title>
- <h1>Thread</h1>
-
- <p>
- <a name="synopsis"></a>
- <h2>Synopsis</h2>
-
- <pre>
-
- class Thread : public ThreadResource, virtual public DeferredDelete
- {
- enum State ;
- public:
- <a href="file:thread#ct">Thread</a>(char *name, int priority = THREAD_BASE_PRIORITY, int newstack = 1) ;
- virtual <a href="file:thread#dt">~Thread</a>() ;
- void <a href="file:thread#start">start</a>() ;
- virtual void <a href="file:thread#run">run</a>() = 0 ;
- virtual void <a href="file:thread#stop">stop</a>() ;
- virtual void <a href="file:thread#resume">resume</a>() ;
- virtual void <a href="file:thread#kill">kill</a>() ;
- virtual void <a href="file:thread#sleep1">sleep</a> (int time) ;
- virtual void <a href="file:thread#sleep2">sleep</a> (ThreadResource *, int pri = THREAD_BASE_PRIORITY) ;
- virtual void <a href="file:thread#wakeup">wakeup</a> () ;
- virtual void <a href="file:thread#write">write</a> (ThreadPipe *pipe, char *buffer, int nbytes) ;
- virtual void <a href="file:thread#read">read</a> (ThreadPipe *pipe, char *buffer, int max, int &nbytes) ;
- void <a href="file:thread#setpriority">setpriority</a> (int pri) ;
- virtual int <a href="file:thread#resource_available">resource_available</a>() ;
- virtual void <a href="file:thread#exit">exit</a> (int status = 0) ;
- virtual void <a href="file:thread#yield">yield</a>() ;
- public:
- int <a href="file:thread#accumulated_cputime">accumulated_cputime</a> ;
- char *<a href="file:thread#name">name</a> ;
- int <a href="file:thread#exit_status">exit_status</a> ;
- } ;
-
- </pre>
-
- <h2>Description</h2>
-
- This class is a preemptive thread. It behaves like a process in an
- operating system like UNIX. All threads in the program execute
- (notionally) simulataneously.
- <p>
- The Task class creates and maintains a set of threads which process the
- events received by the task <b>(except the EREDRAW event which cannot
- be a thread)</b>. It ensures that Wimp_Poll is called
- at the correct frequency by interrupting all running threads at the
- appropriate time. It also shares the available CPU time among the
- running threads in a fair manner to ensure that all threads can
- run.
- <p>
- The user program may create its own threads by deriving a new class from
- the Thread class. The Thread class provides a set of virtual functions
- which should be overridden by the derived class in order to replace or
- enhance the default functionality.
- <p>
- A thread is created by invoking the <a href="file:thread#ct">constructor</a>
- (e.g. using the 'new'
- operator). You must give the thread a name (may be "" if none is
- needed). You may also specify a default <a href="file:thread#pri">priority</a>
- for the thread. Once created, the thread is idle until it is started by calling
- the <a href="file:thread#start">start()</a> function. This function simply places the thread in
- a queue but does not run it right away. When the <a href="file:thread#start">start()</a> function
- returns the thread is ready to run.
- <p>
- A thread starts running by calling its <a href="file:thread#run">run()</a>
- function. This pure
- virtual function must be provided by a derived class and is the
- main body of the thread. When the thread is running it will be
- interrupted by the system in order to give other threads a chance
- at the CPU. Threads are interrupted every centisecond, but it depends
- on the relative priority of the threads whether it gives up the
- CPU or not.
- <p>
- When the <a href="file:thread#run">run()</a> function returns, the thread is stopped and returns
- to idle state from where it may be rerun by calling the <a href="file:thread#start">start()</a>
- function again.
-
- <p>
- <a name="pri"></a>
- <h3>Thread Scheduling</h3>
-
- All threads run simultaneously. Obviously this cannot really happen
- as there is only one processor, so the library shares the CPU
- among the running threads. The threads are kept on a queue
- and when a thread is preempted, the system chooses another thread
- to run. Which thread is chosen depends on the priorities of the
- threads in the queue.
- <p>
- A thread accumulates CPU time. The priority of a thread is a function
- of the amount of time the thread has had on the CPU recently. The system
- chooses the thread with the 'highest' priority. When a thread is
- created, the constructor can be given a 'base priority' with which
- to run the thread. This value is added to the priority calculations
- on a context switch to give the true thread priority.
- <p>
- A thread priority is simply a number. The lower the number the 'higher'
- the priority of the thread. The priorities are recalculated for every
- thread on a 'context switch' and the new value is based on the
- previous priority and the recent CPU usage. The base priority
- can be used to specify whether the thread gets more or less
- CPU time than other threads. The priority values run from
- 0 to 120 with 0 being the highest, 120 the lowest and 60 the
- average. A thread created with a base priotity less than 60
- is known as a 'high priority thread' and will, on average, get
- more CPU time than threads of a lower priority.
- <p>
- When a thread is running there will be occasions when it is known that
- there is nothing to do for a while. Rather than entering a tight loop,
- the thread should <a href="file:thread#yield">yield</a> to another thread which may have something
- to do. This allows more efficient use of the CPU.
-
-
- <h3>Thread Resources</h3>
-
- Threads need to be able to communicate. A thread may <a href="file:thread#sleep2">sleep</a> waiting
- for a 'resource' to become available. A 'ThreadResource' is a
- simple class which contains a single flag. The flag is called
- 'available' and has a non zero value if the resource is available.
- When a thread wants to wait for a resource to become available, it
- called the function 'sleep'. There are two versions of this
- function:
- <p>
- <ol>
- <li><a href="file:thread#sleep2">sleep</a> (ThreadResource *, int pri)
- <li><a href="file:thread#sleep1">sleep</a> (int time)
- </ol>
- <p>
- The first version is the general purpose sleep function. With it a thread
- may sleep until the given resource becomes available. When a thread
- is sleeping it is not using any CPU time. It is awoken by the
- system when a special thread called the 'ResourceThread' notices that
- the resource has become available. The second parameter to the
- function is the priority at which the thread should awaken. This allows
- threads to wake up with differing priorities to adjust the order in which
- they will run.
- <p>
- The second sleep function is really a specialisation of the general
- purpose function. This function allows a thread to sleep for
- a specified period of time (in centiseconds). It makes use
- of a built in resource called a 'ThreadTimer'. The time will
- not be totally accurate but could be a couple of centiseconds
- out depending on the number of threads running.
- <p>
- When a resource becomes available, all threads sleeping on the resource
- will wake up. The highest priority thread (lowest priority number) will
- run first. All threads, when sleeping for a shared resource MUST
- check to ensure that the resource is still available when they wake up.
- If they don't check this, the program will not work properly.
- <p>
- A look at the class definition for a <a href="file:thread#synposis">Thread</a> will show that the Thread
- class is a ThreadResource itself. The resource becomes available
- when the thread terminates execution by returning from the 'run()'
- function or otherwise self terminates. This allows other threads to
- wait for another thread to finish. The <a href="file:thread#exit">exit()</a> function allows
- a thread to exit and set an <a href="file:#threadexit_status">exit status</a> for another thread to
- pick up.
- <p>
- A number of resources have been predefined:
- <pre>
-
- 1. ThreadTimer - A resource which waits for a specified amount of
- time before becoming available
- 2. ThreadPipe - A resource which allows threads to send data through
- a memory based controlled pipe. Threads contain
- member functions to read from and write to pipes.
- If a thread attempts to write to or read from a pipe
- and the resource isn't available, the thread will
- sleep until the pipe clears or has data.
- 3. ThreadSemaphore - This is simply a flag which can be set, cleared and
- read. It should be used by threads to protect
- shared pieces of data from the 'lost update'
- problem. If a thread wishes to update a piece
- of shared data it should sleep until a semaphore
- protecting it has become available. When it awakes
- it should recheck the semaphore and sleep again
- in case another thread has got it first. If it
- gains control of the data (by waking up, checking
- the semaphore and finding it is still available), it
- should make the semaphore unavailable by clearing it.
- The thread can then update the data and notify other
- threads by setting the semaphore.
-
- </pre>
-
-
-
- <h2>Members</h2>
-
- The following are descriptions of the member functions available to users of
- Threads. There are other internal functions and data which are not relevent
- here.
-
- <p>
- <a name="ct"></a>
- <h3>Thread::Thread (char *name,
- int priority = THREAD_BASE_PRIORITY,
- int newstack = 1)</h3>
-
-
- This constructor creates a new thread. The thread is given a name (which may be "").
- The second parameter is the base priority at which the thread will run. This is a
- value added to the actual thread priority. Lower values mean higher priority with
- 60 being the mid point. Threads of higher priotity will get more CPU time on
- average. The last parameter is not relevent to this discussion and is just
- used internally.
-
-
- <p>
- <a name="dt"></a>
- <h3>Thread::~Thread()</h3>
-
- This the the thread destructor. It will stop the thread running and remove it from
- the system. It must only be invoked (using the delete operator) by another thread.
-
-
- <p>
- <a name="start"></a>
- <h3>Thread::start()</h3>
-
- This function starts a thread running. It returns right away after queuing the thread
- to run. The thread will not start for a period of time.
-
-
- <p>
- <a name="run"></a>
- <h3>Thread::run()</h3>
-
- This is a pure virtual function that must be provided by a derived class. It is the
- body of the thread and will be first thing called when the thread begins to
- run. The thread will stop running when this function returns. The function
- can do anything it likes as the system will ensure that other threads get
- a chance to run and Wimp_Poll is called appropriately.
-
-
- <p>
- <a name="stop"></a>
- <h3>Thread::stop()</h3>
-
- This function temporarily suspends a running thread. The thread will be taken
- out of the queue of running threads and will not use any CPU time. The thread
- may be restarted by use of the the resume() function. The function may
- be called by a thread for itself or for another thread.
-
-
- <p>
- <a name="resume"></a>
- <h3>Thread::resume()</h3>
-
- This function causes a stopped thread to begin at the point it left off. The thread
- must have been previously stopped by a call to the stop() function.
-
-
- <p>
- <a name="kill"></a>
- <h3>Thread::kill()</h3>
-
- This function is used to stop a thread in its tracks. The killed thread will
- stop immediately and cannot be resumed. It can, however, be rerun by
- calling the start() function. A thread can kill itself or another thread.
-
-
- <p>
- <a name="sleep1"></a>
- <h3>Thread::sleep(int time)</h3>
-
- This causes a thread to go to sleep for a period of time. The period is
- specified in centiseconds and a thread can cause itself or any other
- thread to go to sleep. It will awake at a set priority when the time
- expires.
-
-
- <p>
- <a name="sleep2"></a>
- <h3> Thread::sleep(ThreadResource *, int pri = THREAD_BASE_PRIORITY)</h3>
-
- This causes a thread to sleep waiting for the given resource to become
- available. The second parameter specifies the priority at which it
- will awaken. This can be used to determine the order in which the
- threads run when awoken.
-
-
- <p>
- <a name="wakeup"></a>
- <h3> Thread::wakeup()</h3>
-
- This causes a sleeping thread to wake up before the resource becomes
- available. Obviously, a thread cannot wake itself up (it is not running),
- but a thread may wake any other thread up. The thread awoken will
- run at the priority at which it slept.
-
-
- <p>
- <a name="write"></a>
- <h3> Thread::write (ThreadPipe *pipe, char *buffer, int nbytes)</h3>
-
- This writes data to the given pipe. The thread will ensure that the
- pipe is available for writing before performing the write. Another
- thread should pick up the data by using the 'read()' call.
-
- The data is written to the pipe from the address passed in
- 'buffer' which is 'nbytes' long. If the data is too big for
- the pipe, it will be split into chunks. The function will return
- when all the data has been written to the pipe (but not
- necessarily picked up).
-
-
- <p>
- <a name="read"></a>
- <h3> Thread::read (ThreadPipe *pipe, char *buffer, int max, int &nbytes)</h3>
-
- This is used to read from a given pipe. Another thread must have written
- data to the pipe before a read can be performed. The 'buffer' parameter
- specifies the address that the data will be read into. 'max' is the
- maximum size of the space available, and 'nbytes' will be set to the
- actual number of bytes read.
-
-
- <p>
- <a name="setpriority"></a>
- <h3> Thread::setpriority(int pri)</h3>
-
- This is used to set the base priority of a thread. Again, the lower the
- value the higher the priority.
-
-
- <p>
- <a name="resource_available"></a>
- <h3> Thread::resource_available()</h3>
-
- This virtual function is called by the ResourceThread to check whether the
- resource for which a thread is sleeping has become available. This may be
- used in the case where a single 'available' flag within the resource is
- insufficient. For example, the ThreadPipe resource is either available
- for read or write, but never both. The resource's 'available' flag
- indicates that there is data in the pipe (ie available for reading). If
- a thread wants to write to the pipe, it must provide a 'resource_available'
- function which checks the pipe's availability for writing (the 'available'
- flag being set to 0). The default behaviour of this function is
- to return the 'available' flag to the caller.
-
-
- <p>
- <a name="exit"></a>
- <h3> Thread::exit (int status = 0)</h3>
-
- This function is used to cause a thread to exit. It is simular to the 'kill'
- function except it allows an exit status to be set for picking up by
- another thread.
-
-
- <p>
- <a name="yield"></a>
- <h3> Thread::yield()</h3>
-
- This function causes a thread to give up the processor in favour of another
- thread. Obviously it can only be called to yield the currently running
- thread. It makes for a better performing program if this function is
- used liberally when it is known there is no work for a thread to do. There
- should be no need to tight loops.
-
-
- <p>
- <a name="accumulated_cputume"></a>
- <h3> Thread::accumulated_cputime</h3>
-
- This variable holds the amount of time a thread has occupied in the CPU.
- It is the number of centiseconds for which the thread has actually been
- running. This is different from the amount of real time since the thread
- was started as threads do not get the CPU to themselves. It is not
- guaranteed to be accurate.
-
-
- <p>
- <a name="name"></a>
- <h3> Thread::name</h3>
-
- This is the name of the thread.
-
-
- <p>
- <a name="exit_status"></a>
- <h3> Thread::exit_status</h3>
-
- This is the value set by the 'exit()' function when a thread terminates.
- It may be used to check the termination status of another thread.
-
- <p>
- <a name="example"></a>
- <h2>Example</h2>
-
- This example shows how to create a simple thread. Once running the thread
- will track the mouse and write the coordinates into an icon in a window
- passed in the constructor. The window must have an icon 0 which must
- be indirected and long enough to hold the text.
- <pre>
-
- //
- // class definition
- //
-
- class MouseTracker : public Thread
- {
- public:
- MouseTracker (Window *w) ; // constructor
- ~MouseTracker() ; // destructor
- void run() ; // run function
- private:
- Window *window ;
- } ;
-
- //
- // member functions
- //
-
- // constructor: creates a thread with name "Tracker" and high priority
-
- MouseTracker::MouseTracker (Window *w)
- : Thread ("Tracker", 55) // priority = high
- {
- window = w ; // just set the variable
- }
-
- // destructor
-
- MouseTracker::~MouseTracker()
- {
- }
-
- //
- // main thread run function. This just loops forever reading the
- // mouse position and printing into an icon
-
- void MouseTracker::run()
- {
- _kernel_swi_regs r ;
- _kernel_oserror *e ;
- int block[5] ;
- Icon *ic = new Icon (window, 0) ; // icon 0
- window->do_open() ; // open the window
- for (;;)
- {
- r.r[1] = (int)block ;
- if ((e = _kernel_swi (Wimp_GetPointerInfo, &r, &r)) != NULL) // get pointer position
- throw e ;
- ic->print ("(%d, %d)",block[0],block[1]) ; // print result
- yield() ; // yield to next thread
- }
- }
-
-
- </pre>
- This simple example shows how to create and run a thread. Many of these
- threads may be running at once. The system will schedule between
- them.
-
-