ThreadPool.hpp
00001 //
00002 // 3D Shape Analysis Library.
00003 // Copyright (C) 2010 AQSENSE, S.L.
00004 //
00005 #if !defined (AQSENSE_SAL3DPP_THREADPOOL_HPP)
00006 #define AQSENSE_SAL3DPP_THREADPOOL_HPP
00007 
00008 #if defined (_MSC_VER) && (_MSC_VER >= 1020)
00009 #pragma once
00010 #endif // _MSC_VER && _MSC_VER >= 1020
00011 
00012 #include <cassert>
00013 #include <stdexcept>
00014 #include <string>
00015 #include <sal3d/threadpool.h>
00016 #include <sal3dpp/Common.hpp>
00017 
00018 namespace sal3d
00019 {
00096     template<typename Task>
00097     class ThreadPool
00098     {
00099         public:
00108             ThreadPool(int nthreads)
00109                 :_nthreads(nthreads)
00110             {
00111                 Error e;
00112                 sal3d_threadpool_new(nthreads, &_threadpool, 0, &e.e);
00113                 if (e.e.value < 0)
00114                     throw e;
00115             }
00116 
00125             ThreadPool(int nthreads, const char *basename)
00126                 :_nthreads(nthreads)
00127             {
00128                 Error e;
00129                 sal3d_threadpool_new(nthreads, &_threadpool, basename, &e.e);
00130                 if (e.e.value < 0)
00131                     throw e;
00132             }
00133 
00138             ~ThreadPool()
00139             {
00140                 sal3d_threadpool_delete(&_threadpool, 0);
00141             }
00142 
00152             void post(const Task &t)
00153             {
00154                 // This will be deleted after running, on callback.
00155                 Task *copy = new Task(t);
00156 
00157                 Error e;
00158                 sal3d_threadpool_post(_threadpool,
00159                         callback,
00160                         reinterpret_cast<void *>(copy), &e.e);
00161                 if (e.e.value < 0)
00162                 {
00163                     delete copy;
00164                     throw e;
00165                 }
00166             }
00167 
00172             void wait()
00173             {
00174                 Error e;
00175                 sal3d_threadpool_wait(_threadpool, &e.e);
00176                 if (e.e.value < 0)
00177                     throw e;
00178             }
00179 
00187             bool wait(int timeout_ms)
00188             {
00189                 Error e;
00190                 sal3d_threadpool_wait_timeout(_threadpool,
00191                         timeout_ms, &e.e);
00192                 if (e.e.value < 0)
00193                 {
00194                     if (e.e.value == SAL3D_ERROR_TIMEOUT)
00195                         return false;
00196                     throw e;
00197                 }
00198                 return true;
00199             }
00200 
00205             int nthreads() const
00206             {
00207                 return _nthreads;
00208             }
00209 
00210         private:
00211             static void callback(void *data)
00212             {
00213                 Task *t = reinterpret_cast<Task *>(data);
00214                 try {
00215                     t->operator()();
00216                 }
00217                 catch(...)
00218                 {
00219                     assert(0 && "Exception thrown in callback for Task");
00220                 }
00221 
00222                 delete t;
00223             }
00224 
00225             /* Uncopiable */
00226             ThreadPool(const ThreadPool &);
00227             ThreadPool& operator=(const ThreadPool &);
00228 
00229             sal3d_threadpool _threadpool;
00230             int _nthreads;
00231     };
00232 }
00233 #endif // !AQSENSE_SAL3DPP_THREADPOOL_HPP