Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages
hugin_base/vigra_ext/MultiThreadOperations.h
Go to the documentation of this file.00001 // -*- c-basic-offset: 4 -*- 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 // divide output image into multiple areas 00095 unsigned nThreads = ThreadManager::get().getNThreads(); 00096 00097 vigra::Diff2D srcSize = src.second - src.first; 00098 // limit amount of threads if only a few lines are given. 00099 if (srcSize.y < (int) nThreads) { 00100 nThreads = srcSize.y; 00101 } 00102 00103 // just our thread 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 // unsigned int lastChunkSize = srcSize.y - (nThreads-1) * chunkSize; 00113 00114 // create threads to remap each area 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 // last chunk 00132 srcCurr.second = src.second; 00133 // remap last chunk in current thread. 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 } // namespace 00143 00144 #endif // _MULTITHREADOPERATIONS_H
1.3.9.1