krita

kis_thread_pool.cc

00001 /*
00002  *  copyright (c) 2006 Boudewijn Rempt
00003  *
00004  *  This program is free software; you can distribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 #include "kis_thread_pool.h"
00020 #include <kglobal.h>
00021 #include <kconfig.h>
00022 #include <kdebug.h>
00023 
00024 KisThreadPool * KisThreadPool::m_singleton = 0;
00025 
00026 KisThreadPool::KisThreadPool()
00027 {
00028     Q_ASSERT(KisThreadPool::m_singleton == 0);
00029 
00030     KisThreadPool::m_singleton = this;
00031 
00032     KConfig * cfg = KGlobal::config();
00033     cfg->setGroup("");
00034     m_maxThreads = cfg->readNumEntry("maxthreads",  10);
00035     m_numberOfRunningThreads = 0;
00036     m_numberOfQueuedThreads = 0;
00037     m_wait = 200;
00038 
00039     start();
00040 }
00041 
00042 
00043 KisThreadPool::~KisThreadPool()
00044 {
00045     m_poolMutex.lock();
00046 
00047     m_canceled = true;
00048 
00049     m_runningThreads.setAutoDelete(true);
00050     m_threads.setAutoDelete(true);
00051     m_oldThreads.setAutoDelete(true);
00052 
00053     KisThread * t;
00054 
00055     for ( t = m_threads.first(); t; t = m_threads.next()) {
00056         if (t) {
00057             t->cancel();
00058             t->wait();
00059             m_threads.remove(t);
00060         }
00061     }
00062 
00063     for ( t = m_runningThreads.first(); t; t = m_runningThreads.next()) {
00064         if (t) {
00065             t->cancel();
00066             t->wait();
00067             m_runningThreads.remove(t);
00068         }
00069     }
00070 
00071     for ( t = m_oldThreads.first(); t; t = m_oldThreads.next()) {
00072         if (t) {
00073             t->cancel();
00074             t->wait();
00075             m_runningThreads.remove(t);
00076         }
00077     }
00078     KisThreadPool::m_singleton = 0;
00079     m_poolMutex.unlock();
00080 
00081 }
00082 
00083 
00084 KisThreadPool * KisThreadPool::instance()
00085 {
00086     if(KisThreadPool::m_singleton == 0)
00087     {
00088         KisThreadPool::m_singleton = new KisThreadPool();
00089     }
00090     else {
00091 
00092         if (KisThreadPool::m_singleton->finished()) {
00093             delete KisThreadPool::m_singleton;
00094             KisThreadPool::m_singleton = 0;
00095             KisThreadPool::m_singleton = new KisThreadPool();
00096         }
00097     }
00098 
00099     return KisThreadPool::m_singleton;
00100 }
00101 
00102 void KisThreadPool::enqueue(KisThread * thread)
00103 {
00104     m_poolMutex.lock();
00105     m_threads.append(thread);
00106     m_numberOfQueuedThreads++;
00107     m_poolMutex.unlock();
00108     m_wait = 200;
00109 }
00110 
00111 
00112 void KisThreadPool::dequeue(KisThread * thread)
00113 {
00114     KisThread * t = 0;
00115 
00116     m_poolMutex.lock();
00117 
00118     int i = m_threads.findRef(thread);
00119     if (i >= 0) {
00120         t = m_threads.take(i);
00121         m_numberOfQueuedThreads--;
00122     } else {
00123         i = m_runningThreads.findRef(thread);
00124         if (i >= 0) {
00125             t = m_runningThreads.take(i);
00126             m_numberOfRunningThreads--;
00127         }
00128         else {
00129             i = m_oldThreads.findRef(thread);
00130             if (i >= 0) {
00131                 t = m_oldThreads.take(i);
00132             }
00133         }
00134     }
00135 
00136     m_poolMutex.unlock();
00137 
00138     if (t) {
00139         t->cancel();
00140         t->wait();
00141         delete t;
00142     }
00143 
00144 }
00145 
00146 void KisThreadPool::run()
00147 {
00148     int sleeps = 10;
00149 
00150     while(!m_canceled) {
00151         if (m_numberOfQueuedThreads > 0 && m_numberOfRunningThreads < m_maxThreads) {
00152             KisThread * thread = 0;
00153             m_poolMutex.lock();
00154             if (m_threads.count() > 0) {
00155                 thread = m_threads.take();
00156                 m_numberOfQueuedThreads--;
00157             }
00158             if (thread) {
00159                 thread->start();
00160                 m_runningThreads.append(thread);
00161                 m_numberOfRunningThreads++;
00162             }
00163             m_poolMutex.unlock();
00164         }
00165         else {
00166             msleep(m_wait);
00167             m_poolMutex.lock();
00168             for ( KisThread * t = m_runningThreads.first(); t; t = m_runningThreads.next()) {
00169                 if (t) {
00170                     if (t->finished()) {
00171                         m_runningThreads.remove(t);
00172                         m_numberOfRunningThreads--;
00173                         m_oldThreads.append(t);
00174                     }
00175                 }
00176             }
00177             m_poolMutex.unlock();
00178             m_poolMutex.lock();
00179             if (m_numberOfQueuedThreads == 0 && m_numberOfRunningThreads == 0) {
00180                 sleeps--;
00181                 if (sleeps == 0) {
00182                     m_poolMutex.unlock();
00183                     return;
00184                 }
00185                 m_poolMutex.unlock();
00186 
00187             }
00188             m_poolMutex.unlock();
00189 
00190         }
00191     }
00192 }
KDE Home | KDE Accessibility Home | Description of Access Keys