/** * This file is part of DSO. * * Copyright 2016 Technical University of Munich and Intel. * Developed by Jakob Engel , * for more information see . * If you use this code, please cite the respective publications as * listed on the above website. * * DSO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * DSO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with DSO. If not, see . */ #pragma once #include "util/settings.h" #include "boost/thread.hpp" #include #include namespace dso { template class IndexThreadReduce { public: EIGEN_MAKE_ALIGNED_OPERATOR_NEW; inline IndexThreadReduce() { nextIndex = 0; maxIndex = 0; stepSize = 1; callPerIndex = boost::bind(&IndexThreadReduce::callPerIndexDefault, this, _1, _2, _3, _4); running = true; for(int i=0;i callPerIndex, int first, int end, int stepSize = 0) { memset(&stats, 0, sizeof(Running)); // if(!multiThreading) // { // callPerIndex(first, end, &stats, 0); // return; // } if(stepSize == 0) stepSize = ((end-first)+NUM_THREADS-1)/NUM_THREADS; //printf("reduce called\n"); boost::unique_lock lock(exMutex); // save this->callPerIndex = callPerIndex; nextIndex = first; maxIndex = end; this->stepSize = stepSize; // go worker threads! for(int i=0;icallPerIndex = boost::bind(&IndexThreadReduce::callPerIndexDefault, this, _1, _2, _3, _4); //printf("reduce done (all threads finished)\n"); } Running stats; private: boost::thread workerThreads[NUM_THREADS]; bool isDone[NUM_THREADS]; bool gotOne[NUM_THREADS]; boost::mutex exMutex; boost::condition_variable todo_signal; boost::condition_variable done_signal; int nextIndex; int maxIndex; int stepSize; bool running; boost::function callPerIndex; void callPerIndexDefault(int i, int j,Running* k, int tid) { printf("ERROR: should never be called....\n"); assert(false); } void workerLoop(int idx) { boost::unique_lock lock(exMutex); while(running) { // try to get something to do. int todo = 0; bool gotSomething = false; if(nextIndex < maxIndex) { // got something! todo = nextIndex; nextIndex+=stepSize; gotSomething = true; } // if got something: do it (unlock in the meantime) if(gotSomething) { lock.unlock(); assert(callPerIndex != 0); Running s; memset(&s, 0, sizeof(Running)); callPerIndex(todo, std::min(todo+stepSize, maxIndex), &s, idx); gotOne[idx] = true; lock.lock(); stats += s; } // otherwise wait on signal, releasing lock in the meantime. else { if(!gotOne[idx]) { lock.unlock(); assert(callPerIndex != 0); Running s; memset(&s, 0, sizeof(Running)); callPerIndex(0, 0, &s, idx); gotOne[idx] = true; lock.lock(); stats += s; } isDone[idx] = true; //printf("worker %d waiting..\n", idx); done_signal.notify_all(); todo_signal.wait(lock); } } } }; }