Main Page | Namespace List | Class List | File List | Namespace Members | Class Members | File Members

thread.h

Go to the documentation of this file.
00001 // $Id: thread.h,v 1.15 2006/06/24 09:39:28 dvermeir Exp $
00002 #ifndef DV_THREAD_THREAD_H
00003 #define DV_THREAD_THREAD_H
00004 
00005 #include <setjmp.h>
00006 #include <dvthread/monitor.h>
00007 #include <iostream>
00008 
00009 /**
00010  * @mainpage
00011  *
00012  * @author dvermeir@vub.ac.be
00013  *
00014  * <a href="../download/">Download</a>
00015  *
00016  * @section Installation Installation
00017  *
00018  * Standard. See the INSTALL file in the top directory.
00019  *
00020  * @section Description Description
00021  * This package provides two main classes: Dv::Thread::Thread,
00022  * representing threads, and Dv::Thread::Monitor, to represent
00023  * monitors. In addition, there is a trivial convenience class
00024  * Dv::Thread::Lock that can be used to conveniently ensure
00025  * exclusive access for member functions to *this (where *this
00026  * is an instance of (a subclass of) Dv::Thread::Monitor.
00027  *
00028  * @section Example Example program
00029  *
00030  * The following class implements a buffer for concurrent access.
00031  * Note the use of the SYNCHRONIZED macro which ensures that the get()
00032  * and put() member functions have exclusive access to the Buffer
00033  * object. Conditions are used to signal threads waiting to put or get
00034  * items into (from) the buffer.
00035  * @include buffer.h 
00036  *
00037  * The example below shows the implementation of a reader thread class
00038  * for the above buffer.
00039  * Each thread should implement a Thread::main() member function
00040  * that describes the work to be done by the thread.
00041  * @include reader.h
00042  *
00043  * This example shows the implementation of a writer thread class.
00044  * Each thread should implement a Thread::main() member function
00045  * that describes the work to be done by the thread.
00046  * @include writer.h
00047  *
00048  * The main program creates a Buffer object, a Reader and
00049  * a Writer thread. Note that the writer wants to put more items
00050  * than will be read. Consequently, it will throw an exception (from
00051  * within Buffer::put()).
00052  * @include test-thread.C
00053  */
00054 namespace Dv {
00055   namespace Thread {
00056     /**
00057      * Posix thread class.
00058      *
00059      * Example Thread class definitions:
00060      * <ul>
00061      * <li> A concurrent Buffer reader class.
00062      * \include reader.h
00063      * <li> A concurrent Buffer writer class.
00064      * \include writer.h
00065      * </ul>
00066      * \see Dv::Thread::Monitor
00067      */
00068     class Thread {
00069     public:
00070       enum errors {
00071         BAD_EXCEPTION = -1 /** status of thread that threw a non-int exception */,
00072         DEFAULT_MAIN = -2 /** status of thread run with default main() */
00073       };
00074 
00075       /** Constructor.
00076        * @param delete_after_main if true, \a delete(t) will
00077        *   be executed after \a t->main() has completed.
00078        * @sa Dv::Thread::Thread::delete_after_main
00079        */
00080       Thread(bool delete_after_main = false) throw (std::runtime_error);
00081     
00082       /** Destructor. */
00083       virtual ~Thread();
00084       /** Start up thread. This function will execute main().
00085        * @return 0 iff ok, system errno else.
00086        * @exception runtime_error if thread is already running.
00087        */
00088       int start() throw (std::runtime_error); 
00089 
00090       /** Main function of thread.
00091        * @return the value to keep in set_status
00092        * Note that this function should not throw any exceptions
00093        * except integers.
00094        * The library will catch any exception e that is thrown erroneously,
00095        * print e.what() on cerr and return an exit status of BAD_EXCEPTION.
00096        * @sa Dv::Thread::Thread::start
00097        * @sa Dv::Thread::Thread::BAD_EXCEPTION
00098        * @sa Dv::Thread::Thread::exit
00099        * @sa Dv::Thread::Thread::set_status
00100        */
00101       virtual int main();
00102     
00103       /** This function is called by the thread as a response to a SIGFPE signal being
00104        * delivered from another thread, using Thread::kill. This function
00105        * is then called  the internal handler for this signal.
00106        * @warning This function should not throw any exceptions or chaos will
00107        * result. Typical usage might be:
00108        * @code
00109        * class MyThread {
00110        * public:
00111        *  ...
00112        *  void main() throw() {
00113        *    while (!killed_ && socket_>>line) {
00114        *      ...
00115        *      }
00116        *    }
00117        *  void killed() throw () {
00118        *    killed_ = true;
00119        *    socket_.close();
00120        *    }
00121        * }
00122        * @endcode
00123        */
00124       virtual void killed() throw () { return; }
00125       /** Wait for this thread to finish.
00126        * @return 0 iff ok, see manpage for @a pthread_self for other
00127        *   possibities.
00128        * @warning only works for non-detached threads.
00129        * @sa Dv::Thread::Thread::detach
00130        * @code
00131        * MyThread t;
00132        * cout << "starting t" << endl;
00133        * t.start();
00134        * cout << "waiting for t to finish" << endl;
00135        * t.join();
00136        * @endcode
00137        */
00138       int join() const throw (); 
00139     
00140       /** Kill a thread. This function delivers a <code>SIGFPE</code> signal to the
00141        * thread using <code>pthread_kill(id_,SIGFPE1)</code>. The signal is caught
00142        * and handled internally by calling Dv::Thread::Thread::killed().
00143        * @exception runtime_error for a thread that tries to kill itself.
00144        * @sa Dv::Thread::Thread::killed
00145        */
00146       int kill() const throw (std::runtime_error); 
00147       /** Return exit status of this thread.
00148        * @return exit status of thread.
00149        */
00150       int status() const { return exit_status_; }
00151       void set_status(int status) { exit_status_ = status; }
00152     
00153       /** Return posix thread id of this thread.
00154        * @return Posix thread id.
00155        */
00156       pthread_t id() const { return id_; }
00157 
00158       /** String representation of thread id of this thread.
00159        * @return string representation of the id of this thread
00160        */
00161       std::string sid() const;
00162     
00163       /** Detach this thread. 
00164        * Threads are created as ``joinable'', this function makes this
00165        * impossible. It also ensures that all resources are freed when the
00166        * thread exits.
00167        * @warning To avoid a memory leak, a thread must be joined or
00168        *   detached.
00169        * @return *this
00170        * @sa Dv::Thread::Thread::join
00171        */
00172       Thread& detach();
00173     
00174       /** Delete this thread object after Thread::main() has completed.
00175        * This feature is handy when there are an unknown number of threads
00176        * that are created using new and the only thing to do after a
00177        * thread has finished is to delete the Thread object.
00178        * 
00179        * The code below shows a typical example.
00180        * @code
00181        * class MyThread: public Dv::Thread::Thread {
00182        * public:
00183        *   MyThread* make(); // factory method to prohibit non-heap allocation.
00184        *   void main();
00185        * private:
00186        *   MyThread(...): Dv::Thread::Thread(true), .. { detach(); .. }  
00187        * };
00188        *
00189        * while (accept) {
00190        *   MyThread::make()->start(); // will delete itself automatically
00191        *   }
00192        * @endcode
00193        * @param yes if true, the object will be deleted after Thread::main
00194        *   has finished.
00195        * @return *this
00196        */
00197       Thread& delete_after_main(bool yes) { delete_after_main_ = yes; return *this; }
00198     
00199       /** Will this thread object be deleted after Thread::main() has completed?
00200        * @return true iff this object will be deleted after Thread::main()
00201        *   finished.
00202        */
00203       bool delete_after_main() { return delete_after_main_; }
00204     
00205       /** Is this thread the currently running thread?
00206        * @return true iff this thread is the currently running thread
00207        * @return false otherwise
00208        */
00209       bool is_self() const;
00210 
00211       /** Is this thread running?
00212        * @return true iff this thread has been created using pthread_create
00213        * @return false otherwise
00214        */
00215       bool running() const { return id_ != 0; }
00216 
00217       /** Return pointer to currently running thread.
00218        * @return pointer to currently running thread, may be 0
00219        *   if the thread was not made by this library.
00220        */
00221       static Thread* self() throw (std::runtime_error);
00222     
00223       /** Return id (pthread_t) of currently running thread.
00224        * This works for any thread; it is actually just call to
00225        * pthread_self.
00226        * @return id of currently running thread.
00227        */
00228       static pthread_t self_id() throw () { return pthread_self(); }
00229     
00230       /** Finish this thread, with status.
00231        * @warning This is implemented by throwing the status integer
00232        * as an exception. Hence is your code catches integers,
00233        * as in
00234        * @code
00235        * try {
00236        *    exit(3);
00237        * }
00238        * catch (integer e) {
00239        * }
00240        * @endcode
00241        * the thread will not exit.
00242        * 
00243        * The implementation of this function was changed between
00244        * versions 0.4 and 0.5 because the previous implementation,
00245        * which used @a pthread_exit, gave problems on systems with
00246        * the nptl thread implementation.
00247        * @param status to return.
00248        */
00249       static void exit(int status); 
00250     
00251       /** Stream to log info on, if not 0. */
00252       static std::ostream* log;
00253     
00254     protected:
00255       /** This function is called by the thread as a response to a SIGFPE signal being
00256        * delivered from another thread, using Dv::Thread::Thread::signal. The signal handler
00257        * is internal.
00258        * Typical usage might be:
00259        * @code
00260        * class MyThread {
00261        * public:
00262        *  ...
00263        *  void main() throw() {
00264        *    while (!killed_ && socket_>>line) {
00265        *      ...
00266        *      }
00267        *  void killed() {
00268        *    killed_ = true;
00269        *    socket_.close();
00270        *    }
00271        * }
00272        * @endcode
00273        * @warning This function should not throw any exceptions or chaos will
00274        * result, because exception throwing from signal handlers is
00275        * currently not supported for some cpu types.
00276        */
00277     private:
00278       /** Posix thread id. */
00279       pthread_t  id_; 
00280       /** Posix thread attributes.  */
00281       pthread_attr_t  attributes_;
00282       /** Exit status of this thread.  */
00283       int  exit_status_; 
00284       /** Forbid cctor. */
00285       Thread(const Thread&); 
00286       /** Forbid assignment.  */
00287       Thread& operator=(const Thread&); 
00288       /** Should this object be deleted after Thread::main has completed?  */
00289       bool delete_after_main_;
00290       /** Is a signal handler for SIGFPE installed? This should really
00291        * be private but it is not since it is set from a C function */
00292       bool signal_handler_installed;
00293     public:
00294       /** Set signal_handler_installed. This function does nothing if
00295        * not called by the thread itself.
00296        * @sa Dv::Thread::Thread::is_self
00297        */
00298       void set_signal_handler_installed();
00299     };
00300   }
00301 }
00302 #endif

dvthread-0.5.0 [22 June, 2006]