00001 /** 00002 \file Robots/LoBot/misc/LoThread.C 00003 \brief This file defines the static data members and non-inline member 00004 functions of the lobot::Thread class. 00005 */ 00006 00007 // //////////////////////////////////////////////////////////////////// // 00008 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00009 // by the University of Southern California (USC) and the iLab at USC. // 00010 // See http://iLab.usc.edu for information about this project. // 00011 // //////////////////////////////////////////////////////////////////// // 00012 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00013 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00014 // in Visual Environments, and Applications'' by Christof Koch and // 00015 // Laurent Itti, California Institute of Technology, 2001 (patent // 00016 // pending; application number 09/912,225 filed July 23, 2001; see // 00017 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00018 // //////////////////////////////////////////////////////////////////// // 00019 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00020 // // 00021 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00022 // redistribute it and/or modify it under the terms of the GNU General // 00023 // Public License as published by the Free Software Foundation; either // 00024 // version 2 of the License, or (at your option) any later version. // 00025 // // 00026 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00027 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00028 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00029 // PURPOSE. See the GNU General Public License for more details. // 00030 // // 00031 // You should have received a copy of the GNU General Public License // 00032 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00033 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00034 // Boston, MA 02111-1307 USA. // 00035 // //////////////////////////////////////////////////////////////////// // 00036 // 00037 // Primary maintainer for this file: mviswana usc edu 00038 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Robots/LoBot/thread/LoThread.C $ 00039 // $Id: LoThread.C 13521 2010-06-06 14:23:03Z mviswana $ 00040 // 00041 00042 //---------------------- ALTERNATIVE DEFINITION ------------------------- 00043 00044 // In case pthreads is missing 00045 #ifndef INVT_HAVE_LIBPTHREAD 00046 00047 #include "Robots/LoBot/thread/LoThread.H" 00048 #include "Robots/LoBot/misc/LoExcept.H" 00049 00050 namespace lobot { 00051 00052 // Static data members 00053 int Thread::m_count ; 00054 pthread_mutex_t Thread::m_count_mutex ; 00055 pthread_cond_t Thread::m_count_zero_condition ; 00056 00057 // Constructor 00058 Thread::Thread() 00059 : m_id(0) 00060 { 00061 throw missing_libs(MISSING_PTHREAD) ; 00062 } 00063 00064 // Empty API 00065 void Thread::start(const std::string&, bool){} 00066 void* Thread::thread_func(void*) {return 0 ;} 00067 void* Thread::thread_func_no_return(void*) {return 0 ;} 00068 int Thread::count() {return 0 ;} 00069 void Thread::wait_all(){} 00070 00071 // Destructor 00072 Thread::~Thread(){} 00073 00074 } // end of namespace encapsulating above empty definition 00075 00076 #else // pthreads available ==> the real McCoy 00077 00078 //------------------------------ HEADERS -------------------------------- 00079 00080 // lobot headers 00081 #include "Robots/LoBot/thread/LoThread.H" 00082 #include "Robots/LoBot/misc/LoExcept.H" 00083 00084 //----------------------------- NAMESPACE ------------------------------- 00085 00086 namespace lobot { 00087 00088 //------------------------ STATIC DATA MEMBERS -------------------------- 00089 00090 // A counter to keep track of the number of extant threads 00091 int Thread::m_count ; 00092 00093 // A mutex to ensure proper access to above counter 00094 pthread_mutex_t Thread::m_count_mutex = PTHREAD_MUTEX_INITIALIZER ; 00095 00096 // Condition variable for signaling main thread when all others are done 00097 pthread_cond_t Thread::m_count_zero_condition = PTHREAD_COND_INITIALIZER ; 00098 00099 //-------------------------- INITIALIZATION ----------------------------- 00100 00101 Thread::Thread() 00102 : m_id(0) 00103 {} 00104 00105 void Thread::start(const std::string& name, bool thread_func_returns_normally) 00106 { 00107 m_name = name ; 00108 00109 pthread_attr_t attr ; 00110 pthread_attr_init(& attr) ; 00111 pthread_attr_setdetachstate(& attr, PTHREAD_CREATE_DETACHED) ; 00112 00113 int create_ok = 0 ; 00114 if (thread_func_returns_normally) 00115 create_ok = pthread_create(& m_id, & attr, 00116 thread_func, 00117 reinterpret_cast<void*>(this)) ; 00118 else 00119 create_ok = pthread_create(& m_id, & attr, 00120 thread_func_no_return, 00121 reinterpret_cast<void*>(this)) ; 00122 if (create_ok != 0) 00123 throw thread_error(THREAD_CREATION_FAILURE) ; 00124 } 00125 00126 //------------------------ THE THREAD FUNCTION -------------------------- 00127 00128 void* Thread::thread_func(void* arg) 00129 { 00130 pthread_mutex_lock(& m_count_mutex) ; 00131 ++m_count ; 00132 pthread_mutex_unlock(& m_count_mutex) ; 00133 00134 Thread* derived_class_instance = reinterpret_cast<Thread*>(arg) ; 00135 derived_class_instance->run() ; 00136 00137 pthread_mutex_lock(& m_count_mutex) ; 00138 --m_count ; 00139 if (m_count <= 0) 00140 pthread_cond_broadcast(& m_count_zero_condition) ; 00141 pthread_mutex_unlock(& m_count_mutex) ; 00142 00143 derived_class_instance->m_id = 0 ; 00144 return 0 ; 00145 } 00146 00147 // Threads that don't return normally from their run() methods should not 00148 // be counted. Otherwise, the wait_all() method won't work properly 00149 // because the thread count will never go down to zero. 00150 void* Thread::thread_func_no_return(void* arg) 00151 { 00152 Thread* derived_class_instance = reinterpret_cast<Thread*>(arg) ; 00153 derived_class_instance->run() ; 00154 //derived_class_instance->m_id = 0 ; 00155 return 0 ; 00156 } 00157 00158 //------------------------- THREAD MANAGEMENT --------------------------- 00159 00160 int Thread::count() 00161 { 00162 int n = -1 ; 00163 pthread_mutex_lock(& m_count_mutex) ; 00164 n = m_count ; 00165 pthread_mutex_unlock(& m_count_mutex) ; 00166 return n ; 00167 } 00168 00169 void Thread::wait_all() 00170 { 00171 pthread_mutex_lock(& m_count_mutex) ; 00172 while (m_count > 0) 00173 pthread_cond_wait(& m_count_zero_condition, & m_count_mutex) ; 00174 pthread_mutex_unlock(& m_count_mutex) ; 00175 } 00176 00177 //----------------------------- CLEAN-UP -------------------------------- 00178 00179 Thread::~Thread(){} 00180 00181 //----------------------------------------------------------------------- 00182 00183 } // end of namespace encapsulating this file's definitions 00184 00185 #endif // INVT_HAVE_PTHREAD 00186 00187 /* So things look consistent in everyone's emacs... */ 00188 /* Local Variables: */ 00189 /* indent-tabs-mode: nil */ 00190 /* End: */