00001
00024 #ifndef _MULTITHREADOPERATIONS_H
00025 #define _MULTITHREADOPERATIONS_H
00026
00027 #include <hugin_shared.h>
00028 #include <hugin_utils/utils.h>
00029
00030 #include <vigra/windows.h>
00031 #include <boost/thread.hpp>
00032 #include <boost/bind.hpp>
00033
00034 #include <vigra/utilities.hxx>
00035
00036 namespace vigra_ext
00037 {
00038
00042 class IMPEX ThreadManager
00043 {
00044
00045 public:
00046 ThreadManager()
00047 {
00048 m_nThreads = 1;
00049 }
00050
00051 virtual ~ThreadManager()
00052 {}
00053
00054 static ThreadManager & get()
00055 {
00056 if (!m_instance) {
00057 m_instance = new ThreadManager();
00058 }
00059 return *m_instance;
00060 }
00061
00062 unsigned getNThreads() {
00063 return m_nThreads;
00064 }
00065
00066 void setNThreads(unsigned n)
00067 {
00068 m_nThreads = n;
00069 }
00070 private:
00071 unsigned m_nThreads;
00072 static ThreadManager * m_instance;
00073 };
00074
00089 template <class SrcIter, class SrcAcc, class DestIter, class DestAcc, class Function>
00090 void multithreadOperation (vigra::triple<SrcIter, SrcIter, SrcAcc> src,
00091 vigra::pair<DestIter, DestAcc> dest,
00092 Function op)
00093 {
00094
00095 unsigned nThreads = ThreadManager::get().getNThreads();
00096
00097 vigra::Diff2D srcSize = src.second - src.first;
00098
00099 if (srcSize.y < (int) nThreads) {
00100 nThreads = srcSize.y;
00101 }
00102
00103
00104 if (nThreads == 1)
00105 {
00106 op(src,dest);
00107 }
00108
00109 DEBUG_DEBUG("creating " << nThreads << " threads for transform");
00110
00111 unsigned int chunkSize = srcSize.y / nThreads;
00112
00113
00114
00115 boost::thread_group threads;
00116
00117 vigra::triple<SrcIter, SrcIter, SrcAcc> srcCurr(src);
00118 vigra::pair<DestIter, DestAcc> destCurr(dest);
00119
00120 srcCurr.second.y -= srcSize.y - chunkSize;
00121
00122 unsigned int i;
00123 for (i = 0; i < nThreads-1; ++i) {
00124 DEBUG_DEBUG("Starting thread " << i);
00125 threads.create_thread(boost::bind(op, srcCurr, destCurr));
00126
00127 srcCurr.first.y += chunkSize;
00128 srcCurr.second.y += chunkSize;
00129 destCurr.first.y += chunkSize;
00130 }
00131
00132 srcCurr.second = src.second;
00133
00134 op(src,dest);
00135
00136 DEBUG_DEBUG("Waiting for threads to join");
00137 threads.join_all();
00138 DEBUG_DEBUG("Threads joined");
00139 }
00140
00141
00142 }
00143
00144 #endif // _MULTITHREADOPERATIONS_H