00001 /** 00002 \file Robots/LoBot/misc/LoThread.H 00003 \brief A thin wrapper around some parts of the pthreads creation and 00004 management API. 00005 00006 This file defines a base class, viz., lobot::Thread, for creating 00007 threads to handle different sensorimotor operations within the 00008 Robolocust system. Robolocust modules that need to create new threads 00009 should use this class rather than the raw pthreads API. 00010 00011 However, it should be noted that lobot::Thread is only for creating 00012 threads and some basic thread management related tasks. Thus, users 00013 have to fall back on raw pthreads for mutexes, condition variables and 00014 other such paraphernalia. 00015 */ 00016 00017 // //////////////////////////////////////////////////////////////////// // 00018 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00019 // by the University of Southern California (USC) and the iLab at USC. // 00020 // See http://iLab.usc.edu for information about this project. // 00021 // //////////////////////////////////////////////////////////////////// // 00022 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00023 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00024 // in Visual Environments, and Applications'' by Christof Koch and // 00025 // Laurent Itti, California Institute of Technology, 2001 (patent // 00026 // pending; application number 09/912,225 filed July 23, 2001; see // 00027 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00028 // //////////////////////////////////////////////////////////////////// // 00029 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00030 // // 00031 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00032 // redistribute it and/or modify it under the terms of the GNU General // 00033 // Public License as published by the Free Software Foundation; either // 00034 // version 2 of the License, or (at your option) any later version. // 00035 // // 00036 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00037 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00038 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00039 // PURPOSE. See the GNU General Public License for more details. // 00040 // // 00041 // You should have received a copy of the GNU General Public License // 00042 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00043 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00044 // Boston, MA 02111-1307 USA. // 00045 // //////////////////////////////////////////////////////////////////// // 00046 // 00047 // Primary maintainer for this file: mviswana usc edu 00048 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Robots/LoBot/thread/LoThread.H $ 00049 // $Id: LoThread.H 13521 2010-06-06 14:23:03Z mviswana $ 00050 // 00051 00052 #ifndef LOBOT_THREAD_DOT_H 00053 #define LOBOT_THREAD_DOT_H 00054 00055 //------------------------------ HEADERS -------------------------------- 00056 00057 // POSIX threads 00058 #ifdef INVT_HAVE_LIBPTHREAD 00059 00060 #include <pthread.h> 00061 00062 #else // fake pthreads API to allow builds to succeed 00063 00064 typedef int pthread_t ; 00065 typedef int pthread_mutex_t ; 00066 typedef int pthread_cond_t ; 00067 00068 #endif 00069 00070 // Standard C++ headers 00071 #include <string> 00072 00073 //----------------------------- NAMESPACE ------------------------------- 00074 00075 namespace lobot { 00076 00077 //------------------------- CLASS DEFINITION ---------------------------- 00078 00079 /** 00080 \class lobot::Thread 00081 \brief An ABC for POSIX threads. 00082 00083 lobot::Thread is an abstract base class for creating threads to handle 00084 different tasks within the Robolocust system. It wraps around some of 00085 the basic creation and management APIs of the POSIX threads library 00086 and provides some additional custom support on top of that. 00087 00088 In terms of the additional custom support alluded to above, 00089 specifically, this class keeps track of the number of threads 00090 currently running and allows the main thread to wait for all the other 00091 threads to die with one convenient API. 00092 00093 Robolocust modules that need to create new threads should use this 00094 class rather than the raw pthreads API. However, only some basic 00095 thread creation and management functions are implemented. This means 00096 that clients have to either fall back on the raw POSIX API or rely on 00097 some other wrapper classes for mutexes, condition variables, etc. 00098 00099 To use this class, simply derive from it and define the run() method. 00100 Then, instantiating the derived class will take care of the mechanics 00101 of creating the thread, keeping track of it, etc. 00102 00103 An important thing to keep in mind when using this class is that the 00104 threads it creates are detached, i.e., it is not possible for another 00105 thread to execute pthread_join() on the thread. This ensures that all 00106 thread resources are immediately cleaned up by the OS when the thread 00107 exits. Naturally, it also prevents other threads from joining with it. 00108 00109 The rationale for this design choice is as follows: the Robolocust 00110 system maintains a central shutdown object that signals all the 00111 threads that it's time to wind-up. Each Robolocust thread is required 00112 to monitor the state of this shutdown object in its main loop and take 00113 appropriate action to gracefully kill itself when the shutdown object 00114 is in the signaled state. Additionally, when shutdown is signaled, the 00115 main thread waits for all the other threads to die and then exits the 00116 application. Thus, there is no need for any thread to wait for another 00117 by joining with it. 00118 00119 NOTE: This class does not prevent clients from creating instances on 00120 the stack (i.e., as local variables). However, doing that would 00121 generally be a Bad Idea because when the local object goes out of 00122 scope, its run() method will no longer be available, which, most 00123 likely, will cause all hell to break loose. 00124 00125 DEVNOTE: We could use the named constructor idiom to require clients 00126 to always create Thread objects with the new operator. However, that 00127 precludes using this class in conjunction with lobot::singleton, which 00128 is why we don't enforce the do-not-create-on-stack policy. 00129 */ 00130 class Thread { 00131 // Prevent copy and assignment 00132 Thread(const Thread&) ; 00133 Thread& operator=(const Thread&) ; 00134 00135 private: 00136 /// Every thread has to have an ID and a name. 00137 //@{ 00138 pthread_t m_id ; 00139 std::string m_name ; 00140 //@} 00141 00142 public: 00143 /// Return this thread's ID. 00144 pthread_t id() const {return m_id ;} 00145 00146 /// Return this thread's name. 00147 const std::string& name() const {return m_name ;} 00148 00149 /// Check if the thread is actually running. 00150 bool running() const {return m_id != 0 ;} 00151 00152 protected: 00153 /// A protected constructor because clients should not be able to 00154 /// directly instantiate this class. 00155 Thread() ; 00156 00157 /// Creating a new thread object doesn't automatically start the 00158 /// thread running. Derived classes *must* call this method in the 00159 /// body of their constructors (usually, towards the end). The reason 00160 /// for this two-step procedure is due to the fact that the thread 00161 /// function implemented in this base class calls the run() method in 00162 /// the derived class. For this to work properly, the derived class 00163 /// object must be fully constructed with its v-table setup for 00164 /// action. If we were to start the new thread running in this class's 00165 /// constructor, it can happen that Thread::thread_func() will crash 00166 /// when it attempts to invoke the pure virtual run() method. 00167 /// 00168 /// Therefore, *all* derived class constructors *must* include a call 00169 /// to Thread::start(). By the time we get into a constructor's body, 00170 /// we can be assured that the object is fully constructed and its 00171 /// v-table properly setup. This ensures that Thread::thread_func() 00172 /// will be able to use the virtual function mechanism to call into 00173 /// the derived class's run() method. 00174 /// 00175 /// Note, however, that client modules do not see this two-step thread 00176 /// creation procedure. A client module simply creates an instance of 00177 /// a Thread subclass without having to fuss around with anything 00178 /// else. Once the instance is created, the thread will automatically 00179 /// start running. The onus here is on subclasses to ensure that this 00180 /// automatic thread creation and starting business actually works 00181 /// from the point of view of client modules. 00182 /// 00183 /// Usually, a derived class's run() method will implement some sort 00184 /// of "main" loop and when that loop exits, the run() method will 00185 /// return. However, in some situations, the main loop may be 00186 /// implemented externally (e.g., glutMainLoop()). Threads that 00187 /// implement run() methods that don't return normally should pass 00188 /// false as the second parameter to Thread::start(). 00189 void start(const std::string& name, 00190 bool thread_func_returns_normally = true) ; 00191 00192 private: 00193 /// This is the thread function for each thread. In this base class, 00194 /// it simply serves as the mechanics for getting the pthreads API to 00195 /// work properly without burdening derived/client classes with the 00196 /// gory details. Instead, derived classes need only derive from this 00197 /// one and then define the run() method. 00198 static void* thread_func(void* arg) ; 00199 00200 /// Normally, a thread's run() method will return normally, i.e., back 00201 /// to the thread_func. This allows thread_func() to keep track of the 00202 /// number of threads currently running. 00203 /// 00204 /// However, in some cases, the run() method may not return to the 00205 /// thread_func. For example, a thread that calls glutMainLoop() will 00206 /// have to terminate itself using pthread_exit() rather than by 00207 /// falling out a of a loop because GLUT controls the thread's main 00208 /// loop and provides no direct means of exiting that loop. 00209 /// 00210 /// In such cases, thread_func_no_return() is used as the thread_func. 00211 /// The difference between this thread_func and the usual one is that 00212 /// it does not increment/decrement the thread count prior to and 00213 /// after the run() method call (because the run() method will never 00214 /// return control to it). 00215 /// 00216 /// What this means is that there may be more or less threads actually 00217 /// running than the count maintained in the Thread class. This is an 00218 /// unfortunate consequence of the run-method-not-returning-normally 00219 /// problem. However, it is necessary to have this mechanism in place 00220 /// to ensure that the Robolocust controller exits without any hassles 00221 /// when such threads are running. If we did not have this workaround 00222 /// in place, the main thread would wait for all threads to die; but 00223 /// thread count would never go down to zero because the run method of 00224 /// a thread whose main loop is implemented "externally" would never 00225 /// return, thus, causing the main thread to wait forever. 00226 /// 00227 /// Moral of the story: limit the number of threads that don't return 00228 /// normally from their run() methods. And, in such threads, be sure 00229 /// to pass false to the second parameter of the start() method. 00230 static void* thread_func_no_return(void* arg) ; 00231 00232 public: 00233 /// This method implements the thread's custom processing. It must be 00234 /// defined by every subclass. 00235 virtual void run() = 0 ; 00236 00237 private: 00238 /// This class keeps track of the number of extant threads with a 00239 /// simple shared counter. 00240 static int m_count ; 00241 00242 /// Since the above counter can be accessed by multiple threads, we 00243 /// need a mutex to ensure serialized updates to the count. 00244 static pthread_mutex_t m_count_mutex ; 00245 00246 public: 00247 /// Return the current number of extant threads. 00248 static int count() ; 00249 00250 private: 00251 /// This class provides an API that allows the main thread to wait for 00252 /// all the other extant threads to die. This condition is signaled 00253 /// using a condition variable that is flagged when the count of 00254 /// extant threads reaches zero. 00255 static pthread_cond_t m_count_zero_condition ; 00256 00257 public: 00258 /// Wait for all the extant threads to die. 00259 /// 00260 /// NOTE: This method is meant to be called *only* by the main thread. 00261 static void wait_all() ; 00262 00263 /// Clean-up. 00264 virtual ~Thread() ; 00265 } ; 00266 00267 //----------------------------------------------------------------------- 00268 00269 } // end of namespace encapsulating this file's definitions 00270 00271 #endif 00272 00273 /* So things look consistent in everyone's emacs... */ 00274 /* Local Variables: */ 00275 /* indent-tabs-mode: nil */ 00276 /* End: */