00001 #ifndef VVELIB_ALGORITHMS_PARALLEL_H
00002 #define VVELIB_ALGORITHMS_PARALLEL_H
00003
00010 #include <config.h>
00011 #include <cstdlib>
00012
00018 namespace parallel
00019 {
00020
00025 struct ThreadEval
00026 {
00027 virtual ~ThreadEval() {}
00028 virtual void operator()() const = 0;
00029 };
00030
00031 class ThreadPoolImpl;
00032
00042 struct ThreadPool
00043 {
00044 ThreadPool();
00045 ~ThreadPool();
00046
00047 int nbProcessors();
00048 int nbThreads();
00049 void setNbThreads(int n);
00050 void setNbThreadsToDefault();
00051
00055 void join();
00056
00057 void clear();
00058
00059 static ThreadPool& threadPool()
00060 {
00061 static ThreadPool* pool = 0;
00062 if(!pool)
00063 {
00064 pool = new ThreadPool();
00065 atexit(&ThreadPool::clearPool);
00066 }
00067 return *pool;
00068 }
00069
00070 static void clearPool()
00071 {
00072 threadPool().clear();
00073 }
00074
00075 template <typename Function>
00076 static void eval(const Function* fct)
00077 {
00078 ThreadPool& pool = threadPool();
00079 if(pool.nbThreads() == 0)
00080 {
00081 (*fct)();
00082 delete fct;
00083 }
00084 else
00085 {
00086 pool.thread_eval(fct);
00087 }
00088 }
00089
00090 protected:
00091 void thread_eval( const ThreadEval* fct);
00092
00093 private:
00094 ThreadPoolImpl *impl;
00095 int nbComputations;
00096 };
00097
00098 inline void threadJoin()
00099 {
00100 ThreadPool& pool = ThreadPool::threadPool();
00101 pool.join();
00102 }
00103
00104 #define ONLY_ARG(F) typename F::argument_type
00105 #define FIRST_ARG(F) typename F::first_argument_type
00106 #define SECOND_ARG(F) typename F::second_argument_type
00107 #define THIRD_ARG(F) typename F::third_argument_type
00108 #define FOURTH_ARG(F) typename F::fourth_argument_type
00109
00113 template <typename Function>
00114 void threadEval(const Function& fct);
00115
00116 template <typename Function>
00117 void threadEval(const Function& fct, ONLY_ARG(Function) a);
00118
00119 template <typename Function>
00120 void threadEval(const Function& fct, FIRST_ARG(Function) a1, SECOND_ARG(Function) a2);
00121
00122 template <typename Function>
00123 void threadEval(const Function& fct, FIRST_ARG(Function) a1, SECOND_ARG(Function) a2, THIRD_ARG(Function) a3);
00124
00125 template <typename Function>
00126 void threadEval(const Function& fct, FIRST_ARG(Function) a1, SECOND_ARG(Function) a2, THIRD_ARG(Function) a3, FOURTH_ARG(Function) a4);
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 template <class Class>
00141 struct MemberFunction0
00142 {
00143 MemberFunction0( void (Class::*m)() )
00144 : mem(m)
00145 { }
00146 void operator()( Class& c ) const
00147 {
00148 (c.*mem)();
00149 }
00150 void (Class::*mem)();
00151 };
00152
00153 template <class Class>
00154 MemberFunction0<Class> memberFunction(void (Class::*m)())
00155 { return MemberFunction0<Class>(m); }
00156
00157 template <class Class, class Arg>
00158 struct MemberFunction1
00159 {
00160 typedef Class& first_argument_type;
00161 typedef Arg second_argument_type;
00162 typedef void result_type;
00163 MemberFunction1( void (Class::*m)(Arg) )
00164 : mem(m)
00165 { }
00166 void operator()( Class& c, Arg a ) const
00167 {
00168 (c.*mem)(a);
00169 }
00170 void (Class::*mem)(Arg);
00171 };
00172
00173 template <class Class, typename Arg>
00174 MemberFunction1<Class,Arg> memberFunction(void (Class::*m)(Arg))
00175 { return MemberFunction1<Class,Arg>(m); }
00176
00177 template <class Class, typename Arg1, typename Arg2>
00178 struct MemberFunction2
00179 {
00180 typedef Class& first_argument_type;
00181 typedef Arg1 second_argument_type;
00182 typedef Arg2 third_argument_type;
00183 typedef void result_type;
00184 MemberFunction2( void (Class::*m)(Arg1,Arg2) )
00185 : mem(m)
00186 { }
00187 void operator()( Class& c, Arg1 a1, Arg2 a2 ) const
00188 {
00189 (c.*mem)(a1,a2);
00190 }
00191 void (Class::*mem)(Arg1,Arg2);
00192 };
00193
00194 template <class Class, typename Arg1, typename Arg2>
00195 MemberFunction2<Class,Arg1,Arg2> memberFunction(void (Class::*m)(Arg1,Arg2))
00196 { return MemberFunction2<Class,Arg1,Arg2>(m); }
00197
00198 template <class Class, typename Arg1, typename Arg2, typename Arg3>
00199 struct MemberFunction3
00200 {
00201 typedef Class& first_argument_type;
00202 typedef Arg1 second_argument_type;
00203 typedef Arg2 third_argument_type;
00204 typedef Arg3 fourth_argument_type;
00205 typedef void result_type;
00206 MemberFunction3( void (Class::*m)(Arg1,Arg2,Arg3) )
00207 : mem(m)
00208 { }
00209 void operator()( Class& c, Arg1 a1, Arg2 a2, Arg3 a3 ) const
00210 {
00211 (c.*mem)(a1,a2,a3);
00212 }
00213 void (Class::*mem)(Arg1,Arg2,Arg3);
00214 };
00215
00216 template <class Class, typename Arg1, typename Arg2, typename Arg3>
00217 MemberFunction3<Class,Arg1,Arg2,Arg3> memberFunction(void (Class::*m)(Arg1,Arg2,Arg3))
00218 { return MemberFunction3<Class,Arg1,Arg2,Arg3>(m); }
00219
00220 template <class Arg>
00221 struct FreeFunction1
00222 {
00223 typedef Arg argument_type;
00224 typedef void result_type;
00225 FreeFunction1(void (*f)(Arg))
00226 : fct(f)
00227 { }
00228 void operator()( Arg a ) const
00229 {
00230 fct(a);
00231 }
00232 void (*fct)(Arg);
00233 };
00234
00235 template <class Arg1>
00236 FreeFunction1<Arg1> freeFunction(void (*f)(Arg1))
00237 { return FreeFunction1<Arg1>(f); }
00238
00239 template <class Arg1, class Arg2>
00240 struct FreeFunction2
00241 {
00242 typedef Arg1 first_argument_type;
00243 typedef Arg2 second_argument_type;
00244 typedef void result_type;
00245 FreeFunction2(void (*f)(Arg1,Arg2))
00246 : fct(f)
00247 { }
00248 void operator()( Arg1 a1, Arg2 a2 ) const
00249 {
00250 fct(a1, a2);
00251 }
00252 void (*fct)(Arg1,Arg2);
00253 };
00254
00255 template <class Arg1, class Arg2>
00256 FreeFunction2<Arg1,Arg2> freeFunction(void (*f)(Arg1,Arg2))
00257 { return FreeFunction2<Arg1,Arg2>(f); }
00258
00259 template <class Arg1, class Arg2, class Arg3>
00260 struct FreeFunction3
00261 {
00262 typedef Arg1 first_argument_type;
00263 typedef Arg2 second_argument_type;
00264 typedef Arg3 third_argument_type;
00265 typedef void result_type;
00266 FreeFunction3(void (*f)(Arg1,Arg2,Arg3))
00267 : fct(f)
00268 { }
00269 void operator()( Arg1 a1, Arg2 a2, Arg3 a3 ) const
00270 {
00271 fct(a1, a2, a3);
00272 }
00273 void (*fct)(Arg1,Arg2,Arg3);
00274 };
00275
00276 template <class Arg1, class Arg2, class Arg3>
00277 FreeFunction3<Arg1,Arg2,Arg3> freeFunction(void (*f)(Arg1,Arg2,Arg3))
00278 { return FreeFunction3<Arg1,Arg2,Arg3>(f); }
00279
00280 template <class Arg1, class Arg2, class Arg3, class Arg4>
00281 struct FreeFunction4
00282 {
00283 typedef Arg1 first_argument_type;
00284 typedef Arg2 second_argument_type;
00285 typedef Arg3 third_argument_type;
00286 typedef Arg4 fourth_argument_type;
00287 typedef void result_type;
00288 FreeFunction4(void (*f)(Arg1,Arg2,Arg3,Arg4))
00289 : fct(f)
00290 { }
00291 void operator()( Arg1 a1, Arg2 a2, Arg3 a3, Arg4 a4 ) const
00292 {
00293 fct(a1, a2, a3, a4);
00294 }
00295 void (*fct)(Arg1,Arg2,Arg3,Arg4);
00296 };
00297
00298 template <class Arg1, class Arg2, class Arg3, class Arg4>
00299 FreeFunction4<Arg1,Arg2,Arg3,Arg4> freeFunction(void (*f)(Arg1,Arg2,Arg3,Arg4))
00300 { return FreeFunction4<Arg1,Arg2,Arg3,Arg4>(f); }
00301
00302 }
00303
00304 #include <algorithms/parallel_impl.h>
00305
00306 #undef FIRST_ARG
00307 #undef SECOND_ARG
00308 #undef THIRD_ARG
00309 #undef FOURTH_ARG
00310
00311 #endif // VVELIB_ALGORITHMS_PARALLEL_H
00312