parallel.cpp

00001 #include "parallel.h"
00002 
00003 #ifdef WIN32
00004 # include <windows.h>
00005 #else
00006 # include <unistd.h>
00007 #endif
00008 
00009 #include <QThread>
00010 #include <QSemaphore>
00011 //#include <QWaitCondition>
00012 #include <QQueue>
00013 #include <QMutex>
00014 #include <QMutexLocker>
00015 
00016 #include <cassert>
00017 #include <iostream>
00018 
00019 #include <qatomic.h>
00020 
00021 namespace parallel
00022 {
00023   using std::cout;
00024   using std::endl;
00025 
00026   class EvalThread;
00027 
00028   struct ThreadPoolImpl
00029   {
00030     ThreadPoolImpl()
00031       : nbThreads(0)
00032     { }
00033 
00034     QSemaphore eval_wait;
00035     QMutex eval_mutex;
00036     QSemaphore result_ready;
00037     QQueue<const ThreadEval*> eval_queue;
00038     QQueue<EvalThread*> to_delete;
00039     int nbThreads;
00040   };
00041 
00042   class EvalThread : public QThread
00043   {
00044   public:
00045     EvalThread(ThreadPoolImpl* c)
00046       : QThread(0)
00047       , com(c)
00048     { }
00049 
00050   protected:
00051     void run()
00052     {
00053       {
00054         QMutexLocker locker(&com->eval_mutex);
00055         cout << "*** EvalThread started: " << (void*)currentThreadId() << " ***" << endl;
00056       }
00057       while(1)
00058       {
00059         const ThreadEval* fct;
00060         com->eval_wait.acquire();
00061         if(com->eval_queue.empty())
00062           break;
00063         {
00064           QMutexLocker locker(&com->eval_mutex);
00065           fct = com->eval_queue.dequeue();
00066         }
00067         (*fct)();
00068         com->result_ready.release();
00069       }
00070       {
00071         QMutexLocker locker(&com->eval_mutex);
00072         cout << "--- EvalThread stoped: " << (void*)currentThreadId() << " ---" << endl;
00073         com->to_delete.enqueue(this);
00074         com->result_ready.release();
00075       }
00076     }
00077 
00078     ThreadPoolImpl *com;
00079 
00080   };
00081 
00082   ThreadPool::ThreadPool()
00083     : impl(new ThreadPoolImpl())
00084     , nbComputations(0)
00085   {
00086     setNbThreadsToDefault();
00087   }
00088 
00089   ThreadPool::~ThreadPool()
00090   {
00091     clear();
00092     delete impl;
00093   }
00094 
00095   void ThreadPool::clear()
00096   {
00097     setNbThreads(0);
00098   }
00099 
00100   void ThreadPool::thread_eval( const ThreadEval* fct )
00101   {
00102     nbComputations++;
00103     impl->eval_queue.enqueue(fct);
00104     impl->eval_wait.release();
00105   }
00106 
00107   void ThreadPool::join()
00108   {
00109     impl->result_ready.acquire(this->nbComputations);
00110     this->nbComputations = 0;
00111     assert(impl->eval_queue.isEmpty());
00112   }
00113 
00114   void ThreadPool::setNbThreads( int n )
00115   {
00116     int nt = impl->nbThreads;
00117     cout << "Changing thread number from " << nt << " to " << n << endl;
00118     if(n > nt)
00119     {
00120       for(int i = nt ; i < n ; ++i)
00121       {
00122         cout << "Creating thread " << i << endl;
00123         EvalThread *t = new EvalThread(impl);
00124         t->start();
00125       }
00126     }
00127     else if(n < nt)
00128     {
00129       join();
00130       impl->eval_wait.release(nt-n);
00131       impl->result_ready.acquire(nt-n);
00132       while(!impl->to_delete.isEmpty())
00133       {
00134         EvalThread* th = impl->to_delete.dequeue();
00135         th->wait();
00136         delete th;
00137       }
00138     }
00139     impl->nbThreads = n;
00140   }
00141 
00142   int ThreadPool::nbProcessors()
00143   {
00144     return QThread::idealThreadCount();
00145   }
00146 
00147   int ThreadPool::nbThreads()
00148   {
00149     return impl->nbThreads;
00150   }
00151 
00152   void ThreadPool::setNbThreadsToDefault()
00153   {
00154     int n = this->nbProcessors();
00155     if( n < 2 )
00156       n = 0;
00157     this->setNbThreads(n);
00158   }
00159 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Generated on Fri May 31 15:37:50 2013 for VVE by  doxygen 1.6.3