00001 // $Id: thread.h,v 1.50 2008/12/21 09:40:47 dvermeir Exp $ 00002 #ifndef DV_THREAD_THREAD_H 00003 #define DV_THREAD_THREAD_H 00004 00005 #include <signal.h> // SIGUSR1 sig_atomic_t 00006 extern "C" { 00007 #include <pthread.h> // posix thread library 00008 } 00009 #include <dvutil/debug.h> 00010 #include <dvthread/barrier.h> 00011 #include <iostream> 00012 00013 /** 00014 * @mainpage 00015 * 00016 * @author dvermeir@vub.ac.be 00017 * 00018 * @section Download Download 00019 * <a href="../download/">download directory</a> 00020 * 00021 * @section Installation Installation 00022 * 00023 * Standard. See the INSTALL file in the top directory. 00024 * 00025 * @c ./configure takes a @a --enable-sig-test option, see Dv::Thread::Thread::sig_set_handler. 00026 * 00027 * @section Description Description 00028 * This package provides two main classes: Dv::Thread::Thread, 00029 * representing threads, and Dv::Thread::Monitor, to represent 00030 * monitors. In addition, there is a trivial convenience class 00031 * Dv::Thread::Lock that can be used to conveniently ensure 00032 * exclusive access for member functions to *this (where *this 00033 * is an instance of (a subclass of) Dv::Thread::Monitor. 00034 * There is also a class Dv::Thread::logstream which is 00035 * a thread-safe version of Dv::Util::logstream. 00036 * The Dv::Thread::Barrier class wraps around pthread barriers. 00037 * 00038 * @section Example Example program 00039 * 00040 * The following class implements a buffer for concurrent access. 00041 * Note the use of the Lock object which ensures that the get() 00042 * and put() member functions have exclusive access to the Buffer 00043 * object. Conditions are used to signal threads waiting to put or get 00044 * items into (from) the buffer. 00045 * 00046 * @include test-buffer.h 00047 * 00048 * The code below shows the implementation of a @c reader thread class 00049 * for the above buffer. 00050 * Each thread should implement a Thread::main() member function 00051 * that describes the work to be done by the thread. 00052 * 00053 * @include test-reader.h 00054 * 00055 * A corresponding writer thread class is shown below. 00056 * 00057 * @include test-writer.h 00058 * 00059 * The main program creates a Buffer object, a Reader and 00060 * a Writer thread. Note that the writer wants to put more items 00061 * than will be read. Consequently, it will throw an exception (from 00062 * within Buffer::put()). 00063 * 00064 * @include test-thread.C 00065 */ 00066 namespace Dv { 00067 namespace Thread { 00068 /** Global Dv::Util debug object that can be used to 00069 * generate trace information from within the package. 00070 * @sa Dv::Thread::Thread 00071 * Example usage: 00072 * @code 00073 * Dv::Thread::logstream log(std::cerr, "label"); 00074 * 00075 * Dv::Thread::thread_debug.set_log(&log); 00076 * // setting debug level of 10 will generate copious output 00077 * Dv::Thread::thread_debug.set_debug(10); 00078 * @endcode 00079 */ 00080 extern Debug thread_debug; 00081 00082 00083 /** Posix thread class. 00084 * @sa Dv::Thread::Monitor 00085 */ 00086 class Thread: public DebugSlave { 00087 public: 00088 /** Singleton class that keeps the relation between 00089 * Dv::Thread::Thread objects and corresponding @c pthread_t 00090 * objects (i.e. thread identifiers in the @c pthread library). 00091 */ 00092 friend class Threads; 00093 enum errors { 00094 BAD_EXCEPTION = -1 /** status of thread that threw a non-int exception */, 00095 DEFAULT_MAIN = -2 /** status of thread run with default main() */ 00096 }; 00097 00098 /** Constructor. Note that there are 2 types of 00099 * debug: for internal debugging of the dvthread library: 00100 * use Dv::Thread::thread_debug . For debugging of derived 00101 * classes write e.g. to @a t.log(). 00102 * @param delete_after_main if true, @a delete(t) will 00103 * be executed after @a t->main() has completed. Since 00104 * joining such a thread may not be possible (the Dv::Thread::Thread object 00105 * may have been auto-deleted by the time another thread 00106 * wants to join it), such 00107 * threads are automatically detached by 00108 * Dv::Thread::Thread::start. 00109 * @param min_debug_level if a debug_master is connected, 00110 * statements such as 00111 * @code 00112 * log(4) << FUNCTION_S << ": trouble" << std::endl; 00113 * @endcode 00114 * will only be executed if the master's level is at least @a min_debug_level 00115 * @param debug_master from where debug info will be taken 00116 * @warning to not set the @c delete_after_main parameter unless 00117 * the thread was created using @c new. Since such threads 00118 * may finish (and be destroyed) anytime, it makes no sense to 00119 * refer to them after they have started. 00120 * Thus a typical usage would be 00121 * @code 00122 * new Thread(true,..)->start(); 00123 * @endcode 00124 * @see Dv::DebugSlave 00125 * @sa Dv::Thread::Thread::delete_after_main 00126 * @sa Dv::DebugSlave 00127 */ 00128 Thread(bool delete_after_main = false, unsigned int min_debug_level = 0, 00129 Debugable *debug_master = 0); 00130 00131 /** Destructor. 00132 * If this function is called by the thread itself, and it has not 00133 * been joined nor detached, the thread will first detach itself. 00134 * Otherwise, it will throw an exception. 00135 * @exception std::logic_error if the thread was neither joined nor detached 00136 * unless the destructor was called by the thread itself, in which case 00137 * an automatic detach will be done during the destruction. 00138 * @exception std::logic_error iff the executing thread is not this 00139 * thread and this thread was not yet detached or joined. 00140 */ 00141 virtual ~Thread(); 00142 00143 /** Start up thread, executing the @a main function of this 00144 * Thread object. Upon return, the 00145 * new thread has actually already received some CPU time 00146 * (actually, it may already have finished). 00147 * @return 0 iff ok 00148 * @return errno iff @a pthread_create failed. 00149 * @exception runtime_error if thread is already running. 00150 * @warning Upon failure, the Thread subject is not deleted, not even 00151 * if the thread was created with delete_after_main=true, 00152 * @sa Dv::Thread::Thread::running 00153 */ 00154 int start(); 00155 friend int start(Thread& t); 00156 00157 /** Main function of thread. 00158 * @return the value to keep in status 00159 * Note that this function should not throw any exceptions 00160 * except integers. 00161 * The library will catch any exception e that is thrown erroneously, 00162 * print e.what() on cerr and return an exit status of BAD_EXCEPTION. 00163 * @sa Dv::Thread::Thread::start 00164 * @sa Dv::Thread::Thread::BAD_EXCEPTION 00165 * @sa Dv::Thread::Thread::exit 00166 * @sa Dv::Thread::Thread::set_status 00167 */ 00168 virtual int main(); 00169 00170 /** Wait for a non-detached thread to finish. If the argument thread 00171 * is not detached, it will be joined using @c pthread_join. 00172 * If the thread never started, the return value will be 0. 00173 * @warning Do not use this on threads that were created 00174 * with the @c delete_after_main function. Besides being 00175 * automatically detached, such threads may have been 00176 * deleted already at the time of the call to join, making 00177 * the references to members in the code of 00178 * Dv::Thread::Thread::join unsafe. 00179 * @return 0 iff ok, see manpage for @a pthread_join for other 00180 * possibities. 00181 * @sa Dv::Thread::Thread::detach 00182 * @sa Dv::Thread::Thread::detached_by 00183 * @sa Dv::Thread::Thread::running 00184 * @code 00185 * MyThread t; 00186 * cout << "starting t" << endl; 00187 * t.start(); 00188 * cout << "waiting for t to finish" << endl; 00189 * join(t); 00190 * @endcode 00191 * @exception std::logic_error if, by chance, the 00192 * system correctly detects that the thread was detached and/or 00193 * created using @c delete_after_main. 00194 * @see Dv::Thread::Thread::running 00195 * @see Dv::Thread::Thread::wait 00196 */ 00197 int join(); 00198 00199 /** Wait for a thread to stop running. This works 00200 * even for detached threads or threads that have been deleted (e.g. threads 00201 * that were created using the @c delete_after_main 00202 * option). 00203 * @see Dv::Thread::Thread::join 00204 */ 00205 void wait(); 00206 00207 /** Kill a thread. By default, this function simply sets killed_. 00208 * If the thread is no longer running, this function has 00209 * no effect. This function is 'delete-after-main' safe. 00210 * @return 0 iff the operation succeeded 00211 * @exception std::logic_error iff a thread tries to kill itself 00212 * @sa Dv::Thread::Thread::killed 00213 * @sa Dv::Thread::Thread::sig_set_handler 00214 */ 00215 virtual void kill(int signal = SIGUSR1); 00216 00217 /** Return exit status of this thread. 00218 * @warning this function should not be used on 00219 * 'delete-after-main' threads. 00220 * @return exit status of thread. 00221 */ 00222 int status() const { return exit_status_; } 00223 00224 /** Return posix thread id of this thread. 00225 * @warning this function should not be used on 00226 * 'delete-after-main' threads. 00227 * @return Posix thread id. 00228 */ 00229 pthread_t id() const { return id_; } 00230 00231 /** String representation of thread id of this thread. 00232 * @warning this function should not be used on 00233 * 'delete-after-main' threads. 00234 * @return string representation of the id of this thread 00235 */ 00236 std::string sid() const; 00237 00238 /** Detach this thread. 00239 * Threads are created as ``joinable'', this function makes this 00240 * impossible. It also ensures that all resources are freed when the 00241 * thread exits. 00242 * @warning this function should not be used on 00243 * 'delete-after-main' threads. 00244 * @warning To avoid a memory leak, a thread must be joined or 00245 * detached. 00246 * @return 0 if successful 00247 * @return status returned by @a pthread_detach otherwise 00248 * @warning Detaching a thread that is not yet started will 00249 * return @a EINVAL 00250 * @sa Dv::Thread::Thread::join 00251 * @sa Dv::Thread::Thread::detached_by 00252 */ 00253 int detach() const; 00254 00255 00256 /** Is this thread the currently running thread? This 00257 * function is 'delete-after-main safe'. 00258 * @return true iff this thread is the currently running thread 00259 * @return false otherwise 00260 */ 00261 bool is_self() const; 00262 00263 /** Is this thread running? 00264 * @warning if the thread was created using @c 00265 * delete_after_main, it may be that 'this' is no 00266 * longer valid. However, this function should 00267 * still work since it does not touch any members 00268 * of Dv::Thread::Thread. 00269 * @return true iff this thread has been started 00270 * using Dv::Thread::Thread::start, it has already 00271 * been in the 'running' state at least once and it 00272 * has not yet finished executing its Dv::Thread::Thread::main 00273 * function. 00274 * @return false otherwise 00275 */ 00276 bool running() const; 00277 00278 /** Return pointer to currently running thread or 0. 00279 * @return pointer to currently running thread, 00280 * @return 0 if the thread was not made by this library. 00281 */ 00282 static Thread* self(); 00283 00284 /** Return id (@c pthread_t ) of the currently running thread. 00285 * This works for any thread; it is actually just a call to 00286 * pthread_self. 00287 * @return id of currently running thread. 00288 */ 00289 static pthread_t self_id() throw () { return pthread_self(); } 00290 00291 /** Safe version of sleep which uses a 'dummy' Monitor::wait */ 00292 static void sleep(size_t millisecs); 00293 00294 /** Has this thread been joined? 00295 * @return @a pthread_t id of thread that has joined this thread. 00296 * @return 0 if no thread has joined this thread yet 00297 * @warning this function should not be used on 00298 * 'delete-after-main' threads. 00299 * @sa Dv::Thread::Thread::join 00300 */ 00301 pthread_t joined_by() const { return joiner_; } 00302 00303 /** Has this thread been detached? 00304 * @return @a pthread_t id of thread that has detached this thread. 00305 * @return 0 if no thread has detached this thread yet 00306 * @warning this function should not be used on 00307 * 'delete-after-main' threads. 00308 * @sa Dv::Thread::Thread::detach 00309 */ 00310 pthread_t detached_by() const { return detacher_; } 00311 00312 /** Wait for all threads to have finished. 00313 * @warning there should be no possibility for threads 00314 * to be created (in another running thread) while 00315 * this function is called. 00316 * Typically, this function is called at the end 00317 * of the program by the only thread-creating (main) thread. 00318 * @warning this function does not join any thread, 00319 * it simply observes the set of running Dv::Thread::Thread 00320 * objects until it is empty. 00321 * @return the number of threads waited for 00322 */ 00323 static size_t wait_for_all(); 00324 00325 /** Set signal handler for all threads (in this process). 00326 * The handling of OS signals in C++ (and multi-threaded applications) is 00327 * problematic: 00328 * - A conceptually nice idea of translating a signal to an exception (i.e. let the 00329 * handler function throw an exception) almost never works, see the 00330 * example file @c test-signal-exception.C included with the distribution. 00331 * - Moreover, there 00332 * are strong restrictions on what can be done in a signal handler. 00333 * 00334 * The present implementation only provides a bare-bones minimal solution 00335 * which seems to work reasonably well: 00336 * - Signal handlers (recall that all threads share the same signal disposition, i.e. 00337 * the handler (or absence thereof) can be set to arbitrary functions using the 00338 * @a static @a Dv::Thread::Thread::sig_set_handler(int, void (*)(int). 00339 * - Signals can be (un)blocked (for the currently running thread) using 00340 * - @a static @a Dv::Thread::Thread::sig_block and 00341 * - @a static @a Dv::Thread::Thread::sig_unblock. 00342 * - A simple 'safe' (hopefully) handler is available as 00343 * @a static @a Dv::Thread::Thread::sig_handler(int) . 00344 * It simply sets the volatile @c sig_atomic_t @c killed_ associated with that thread 00345 * to the signal number. Note that, by default, no handlers are set. 00346 * - The default implementation of Dv::Thread::Thread::kill does not 00347 * use signals at all: it simply calls the default signal handler. See 00348 * @c test-default-sig-handler.C for an example of an implementation 00349 * of Dv::Thread::Thread::kill(int) that does deliver a signal. 00350 * 00351 * 00352 * This implementation uses @a sigact. 00353 * @param signal for which handler is set 00354 * @param handler to call if signal s is received 00355 * @param sigaction_flags passed as @a sa_mask in @a sigaction, see 00356 * the man page for @c sigaction(2). 00357 * @return 0 if all went well 00358 * @return -1 if @a sigemptyset failed 00359 * @return -2 if @a sigaddset failed 00360 * @return -3 if @a sigaction failed 00361 * @warning Uses @a pthread_sigmask, not @a sigprocmask 00362 * @sa Dv::Thread::Thread::sig_set_handler 00363 * @sa Dv::Thread::Thread::sig_handler 00364 * @sa Dv::Thread::Thread::sig_block 00365 * @sa Dv::Thread::Thread::sig_unblock 00366 * @sa Dv::Thread::Thread::kill 00367 */ 00368 static int sig_set_handler(int signal = SIGUSR1, 00369 void (*handler)(int) = Dv::Thread::Thread::sig_handler, int sigaction_flags = 0); 00370 /** Default signal handler. This handler will set the @a killed_ 00371 * data member for the thread receiving the signal. 00372 * @param signal used by @a pthread_kill 00373 * @sa Dv::Thread::Thread::sig_set_handler 00374 * @sa Dv::Thread::Thread::sig_handler 00375 * @sa Dv::Thread::Thread::sig_block 00376 * @sa Dv::Thread::Thread::sig_unblock 00377 * @sa Dv::Thread::Thread::kill 00378 */ 00379 static void sig_handler(int signal); 00380 00381 /** Block or unblock a signal for the currently running thread. 00382 * This implementation uses @a pthread_sigmask. 00383 * @param signal to (un)block 00384 * @param unblock if true, unblock instead of block the signal 00385 * @return 0 if all went well 00386 * @return -1 if @a sigemptyset failed 00387 * @return -2 if @a sigaddset failed 00388 * @return -3 if @a pthread_sigmask failed 00389 * @sa Dv::Thread::Thread::sig_set_handler 00390 * @sa Dv::Thread::Thread::sig_handler 00391 * @sa Dv::Thread::Thread::sig_block 00392 * @sa Dv::Thread::Thread::sig_unblock 00393 * @sa Dv::Thread::Thread::kill 00394 */ 00395 static int sig_block(int signal, bool unblock=false); 00396 00397 /** Unblock a signal for the currently running thread. 00398 * This implementation uses @a pthread_sigmask. 00399 * @param signal to unblock 00400 * @return 0 if all went well 00401 * @return -1 if @a sigemptyset failed 00402 * @return -2 if @a sigaddset failed 00403 * @return -3 if @a pthread_sigmask failed 00404 * @sa Dv::Thread::Thread::sig_set_handler 00405 * @sa Dv::Thread::Thread::sig_handler 00406 * @sa Dv::Thread::Thread::sig_block 00407 * @sa Dv::Thread::Thread::sig_unblock 00408 * @sa Dv::Thread::Thread::kill 00409 */ 00410 static int sig_unblock(int signal); 00411 00412 protected: 00413 00414 /** Finish this thread, with status. 00415 * This function is 'delete-after-main safe'. 00416 * @param status to return. 00417 * @warning This function must be called by the running thread itself, 00418 * i.e. @c this==Dv::Thread::Thread::self() must hold 00419 * @warning This is implemented by throwing the status integer 00420 * as an exception. Hence if your code catches integers, 00421 * as in 00422 * @code 00423 * try { 00424 * exit(3); 00425 * } 00426 * catch (integer e) { 00427 * } 00428 * @endcode 00429 * the thread will not exit. 00430 * 00431 * The implementation of this function was changed between 00432 * versions 0.4 and 0.5 because the previous implementation, 00433 * which used @a pthread_exit, gave problems on systems with 00434 * the nptl thread implementation. 00435 * @exception std::logic_error if the calling thread is not this thread 00436 * @sa Dv::Thread::Thread::main 00437 */ 00438 void exit(int status); 00439 00440 /** @return value of @a killed_ 00441 * @warning this function should not be used on 00442 * 'delete-after-main' threads. 00443 * @sa Dv::Thread::Thread::kill 00444 * @sa Dv::Thread::Thread::sig_set_handler 00445 * @sa Dv::Thread::Thread::sig_handler 00446 * @sa Dv::Thread::Thread::sig_block 00447 * @sa Dv::Thread::Thread::sig_unblock 00448 * @sa Dv::Thread::Thread::sig_handler 00449 */ 00450 int killed() const { 00451 return killed_; 00452 } 00453 00454 /** Set by default signal handler. 00455 * @sa Dv::Thread::Thread::kill 00456 * @sa Dv::Thread::Thread::killed 00457 */ 00458 volatile sig_atomic_t killed_; 00459 private: 00460 /** Will this thread object be deleted after Thread::main() has completed? 00461 * @warning this function should not be used on 00462 * 'delete-after-main' threads. 00463 * @return true iff this object will be deleted after Thread::main() 00464 * finished. 00465 */ 00466 bool delete_after_main() const { return delete_after_main_; } 00467 00468 bool at_end() const { return at_end_; } 00469 /** Posix thread id. */ 00470 pthread_t id_; 00471 /** Posix thread attributes. */ 00472 pthread_attr_t attributes_; 00473 /** Exit status of this thread. */ 00474 int exit_status_; 00475 /** Forbid cctor. */ 00476 Thread(const Thread&); 00477 /** Forbid assignment. */ 00478 Thread& operator=(const Thread&); 00479 /** Should this object be deleted after Thread::main has completed? */ 00480 bool delete_after_main_; 00481 /** pthread_t id of thread that has joined this thread or 0 */ 00482 pthread_t joiner_; 00483 /** pthread_t id of thread that has detached this thread or 0 */ 00484 pthread_t detacher_; 00485 /** we disable this */ 00486 int cancel_state_; 00487 /** private barrier, used to synchronize parent and new thread */ 00488 Barrier barrier_; 00489 /** set at end of Dv::Thread::Thread::run_thread */ 00490 bool at_end_; 00491 /** Startup function wrapping around @a t->main, passed to @a pthread_create 00492 * @param t thread to start running 00493 */ 00494 static void* run_thread(Dv::Thread::Thread* t); 00495 /** Set the exit status of this thread. 00496 * @param status to set as exit status, normally result of main() 00497 */ 00498 void set_status(int status) { exit_status_ = status; } 00499 }; 00500 /** Start up thread, executing the @a main function of this 00501 * Thread object. Upon return, the 00502 * new thread has actually already received some CPU time 00503 * (actually, it may already have finished). 00504 * @param t thread to start up 00505 * @return 0 iff ok 00506 * @return errno iff @a pthread_create failed. 00507 * @exception runtime_error if thread is already running. 00508 * @warning Upon failure, the Thread subject is not deleted, not even 00509 * if the thread was created with delete_after_main=true, 00510 * @sa Dv::Thread::Thread::running 00511 */ 00512 int start(Thread& t); 00513 00514 } 00515 } 00516 #endif
dvthread-0.13.4 | [11 December, 2009] |