// This is an implementation file for the ThreadManager #include "math_tree.hpp" #include "switches.hpp" #include "thread_manager.hpp" #include "solver.hpp" using namespace std; using boost::logic::tribool; using boost::thread; /////////////////////////////////////////////////////////////////////////////// template ThreadManager::ThreadManager(FabVars& v) : v(v), task_buffer(thread::hardware_concurrency()) { // Nothing to do here. } /////////////////////////////////////////////////////////////////////////////// // Evaluates an entire math tree on the full spatial region. template void ThreadManager::evaluate(MathTree* tree) { list regions; if (v.projection) regions = Region(v).split_xy(task_buffer.size); else regions = Region(v).split(task_buffer.size); // Create a task for each region list::iterator it; for (it = regions.begin(); it != regions.end(); ++it) { // cout << "Added region " << *it << endl; if (!task_buffer.add(*it, tree)) { cout << "Failed to add initial task to task buffer!" << endl; exit(1); } } // Create a new thread for all but one of the tasks for (unsigned i = 1; i < task_buffer.size; ++i) make_new_thread(); // This thread gets a task as well. SOLVER_TYPE* s = new SOLVER_TYPE(v); s->set_buffer(&task_buffer); s->run(); delete s; wait_for_threads(); } /////////////////////////////////////////////////////////////////////////////// template void ThreadManager::make_new_thread() { SOLVER_TYPE* s = new SOLVER_TYPE(v); s->set_buffer(&task_buffer); thread* newThread = new thread(&Solver::run, s); threads.push_back(make_pair(newThread, s)); } /////////////////////////////////////////////////////////////////////////////// template void ThreadManager::wait_for_threads() { while (!threads.empty()) { typename ThreadList::iterator it = threads.begin(); while(it != threads.end()) if (it->first->timed_join(boost::system_time())) { delete it->first; delete it->second; it = threads.erase(it); } else { ++it; } } }