00001 /****************************************************************************** 00002 * __ _ _ _ _ _ _____ * 00003 * | \ / | | | | | | | | | | ___| * 00004 * | \/ | | | | | | | | | | |_ * 00005 * | | | | | | | | | | | _| * 00006 * | |\/| | | | | |__ | |__ | | | |__ * 00007 * |_| |_| |_| |____| |____| |_| |____| * 00008 * __________________________________________________________________________ * 00009 * Multifunctional Library For Image Processing * 00010 * * 00011 * * 00012 * * 00013 * (c) Copyright 2007 by Humbert Florent * 00014 * * 00015 * This program is free software; you can redistribute it and/or modify * 00016 * it under the terms of the GNU General Public License as published by * 00017 * the Free Software Foundation; only version 2 of the License. * 00018 * * 00019 * This program is distributed in the hope that it will be useful, * 00020 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00021 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00022 * GNU General Public License for more details. * 00023 * * 00024 * You should have received a copy of the GNU General Public License * 00025 * along with this program; if not, write to the Free Software * 00026 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 00027 * 02111-1307, USA. * 00028 ******************************************************************************/ 00029 00032 #include "ThreadGroup.hpp" 00033 00034 00035 using namespace Millie; 00036 00042 void ThreadGroup::init() 00043 { 00044 _isRunning = false; 00045 _isStarted = false; 00046 _nbwaitingthread = 0; 00047 00048 00049 pthread_mutex_init(&_mutexWaitAll, 0); 00050 pthread_cond_init(&_waitSynchro, 0); 00051 } 00052 00053 ThreadGroup::ThreadGroup() 00054 { 00055 init(); 00056 } 00057 00058 ThreadGroup::ThreadGroup(const std::string & name) 00059 { 00060 _name = name; 00061 init(); 00062 } 00063 00064 bool ThreadGroup::isStarted() 00065 { 00066 MutexLock mlock(_synchronizedIsStarted); 00067 return _isStarted; 00068 } 00069 00070 bool ThreadGroup::isRunning() 00071 { 00072 MutexLock mlock(_synchronizedIsRunning); 00073 return _isRunning; 00074 } 00075 00076 const std::string & ThreadGroup::getName() const 00077 { 00079 return _name; 00080 } 00081 00082 00083 void ThreadGroup::joinAll() 00084 { 00085 00090 if(isStarted()) 00091 { 00092 for(unsigned int i = 0; i< _vectThread.size(); i++) 00093 { 00094 _vectThread[i]->join(); 00095 } 00096 00097 MutexLock plock(_synchronizedIsRunning); 00099 _isRunning = false; 00100 } 00102 } 00103 00104 unsigned int ThreadGroup::getNbGThread() 00105 { 00106 MutexLock mlock(_synchronizedNbThread); 00107 00108 return(_vectThread.size()); 00109 } 00110 00111 int ThreadGroup::getNbWaitingGThread() 00112 { 00113 MutexLock mlock(_synchronizedWaitingThread); 00114 return _nbwaitingthread; 00115 } 00116 00117 bool ThreadGroup::threadWaitAll(GThread * t, pthread_mutex_t ** mutex, pthread_cond_t ** wait) 00118 { 00119 00121 if(!isStarted()) 00122 { 00123 throw IllegalThreadStateException("ThreadWaitAll : group is not started"); 00124 } 00125 00129 MutexLock mlock(_synchronizedWaitingThread); 00130 00134 MutexLock plock(_synchronizedNbThread); 00135 00139 pthread_mutex_lock(&_mutexWaitAll); 00140 00141 bool b = false; 00142 00146 for(unsigned int i = 0; i<_vectThread.size(); i++) 00147 { 00148 if(_vectThread[i]== t && !(_vectWaiting[i]==true) ) 00149 { 00150 b = true; 00151 _vectWaiting[i] = true; //maintenant il va attendre 00152 break; 00153 } 00154 } 00155 00159 if(b==false) 00160 { 00161 pthread_mutex_unlock(&_mutexWaitAll); 00162 throw RuntimeThreadException("Thread doesn't exist"); 00163 } 00164 00169 *mutex = &_mutexWaitAll; 00170 *wait = &_waitSynchro; 00171 00172 00176 if(_nbwaitingthread == _vectThread.size()-1) 00177 { 00181 for(unsigned int i = 0; i<_vectThread.size(); i++) 00182 _vectWaiting[i] = false; 00183 00187 _nbwaitingthread = 0; 00188 00189 00193 pthread_cond_broadcast(&_waitSynchro); 00194 00198 pthread_mutex_unlock(&_mutexWaitAll); 00199 00203 return false; 00204 } 00205 else 00206 { 00211 _nbwaitingthread++; 00212 return true; 00213 } 00214 } 00215 00216 void ThreadGroup::notifyAll() 00217 { 00218 if(!isStarted()) 00219 throw IllegalThreadStateException("ThreadGroup::notifyAll : is not started"); 00220 00224 for(unsigned int i = 0; i<_vectThread.size();i++) 00225 { 00226 _vectThread[i]->notify(); 00227 _vectWaiting[i] = false; 00228 } 00229 _nbwaitingthread = 0; 00230 } 00231 00232 void ThreadGroup::startAll() 00233 { 00234 00235 MutexLock nbthread(_synchronizedNbThread); 00236 MutexLock startAll(_synchronizedIsStarted); 00237 MutexLock isRunning(_synchronizedIsRunning); 00238 00239 _isStarted = true; 00240 _isRunning = true; 00241 for(unsigned int i = 0; i< _vectThread.size(); i++) 00242 { 00243 std::cerr<<"Start thread "<<i<<std::endl; 00244 _vectThread[i]->start(); 00245 } 00246 } 00247 00248 void ThreadGroup::add(GThread * thread) 00249 { 00250 MutexLock started(_synchronizedIsStarted); 00251 00255 if(_isStarted) 00256 { 00260 delete thread; 00261 throw IllegalThreadStateException("ThreadGroup : add"); 00262 } 00263 00264 thread->setGroup(this); 00265 00266 00267 00268 MutexLock mlock(_synchronizedNbThread); 00269 00270 for(unsigned int i = 0; i<_vectThread.size(); i++) 00271 if(thread == _vectThread[i]) 00272 { 00273 throw IllegalArgument("ThreadGroup : thread still add"); 00274 } 00275 00280 _vectThread.push_back(thread); 00281 _vectWaiting.push_back(false); 00282 00283 } 00284 00285 ThreadGroup::~ThreadGroup() 00286 { 00290 joinAll(); 00291 00295 pthread_mutex_destroy(&_mutexWaitAll); 00296 00297 00298 pthread_cond_destroy(&_waitSynchro); 00299 00300 for(unsigned int i =0; i< _vectThread.size(); i++) 00301 { 00305 delete _vectThread[i]; 00306 _vectThread[i] = 0; 00307 } 00308 _vectThread.clear(); 00309 _vectWaiting.clear(); 00310 } 00311 00312 00313 GThread & ThreadGroup::operator[](unsigned int pos) 00314 { 00315 MutexLock mlock(_synchronizedNbThread); 00316 00317 if(pos < _vectThread.size()) 00318 return *_vectThread[pos]; 00319 else 00320 throw OutOfRange("ThreadGroup::operator[] : bad access"); 00321 } 00322