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

Generated on Thu Jul 31 01:25:42 2014 for Hugintrunk by  doxygen 1.3.9.1