void mt_task_queue::submit_core(gtask const & t, unsigned prio) { if (!t) return; switch (get_state(t).load()){ case task_state::Created: get_data(t)->m_sched_info.reset(new mt_sched_info(prio)); if (check_deps(t)) { if (get_state(t).load() < task_state::Running) { // TODO(gabriel): we need to give up the lock on m_mutex for this if (false && get_data(t)->m_flags.m_eager_execution) { get_state(t) = task_state::Running; execute(t); handle_finished(t); } else { enqueue(t); } } } else { get_state(t) = task_state::Waiting; m_waiting.insert(t); notify_queue_changed(); } break; case task_state::Waiting: case task_state::Queued: bump_prio(t, prio); break; case task_state::Running: case task_state::Failed: case task_state::Success: break; } lean_always_assert(get_state(t).load() >= task_state::Waiting); }
void mt_task_queue::cancel_core(gtask const & t) { if (!t) return; switch (get_state(t).load()) { case task_state::Waiting: m_waiting.erase(t); /* fall-thru */ case task_state::Created: case task_state::Queued: fail(t, std::make_exception_ptr(cancellation_exception())); handle_finished(t); return; default: return; } }
void MainGUI::toggle_rendering(bool is_world_bad) { if (is_world_bad) { handle_finished(); QMessageBox msgBox; msgBox.setText("Invalid world! Check if you have selected the right folder."); msgBox.setIcon(QMessageBox::Warning); msgBox.exec(); return; } bf->set_settings(set); mf->set_nbt(bf); delete scene; scene = new QGraphicsScene(); mf->reset_view(scene); start_button->setText("Abort rendering"); start_button->setEnabled(true); waiter_thread = boost::thread(boost::bind(&MainGUI::start_populate_scene_thread, this)); }
void mt_task_queue::handle_finished(gtask const & t) { lean_always_assert(get_state(t).load() > task_state::Running); lean_always_assert(get_data(t)); if (!get_data(t)->m_sched_info) return; // task has never been submitted m_waiting.erase(t); get_sched_info(t).notify(); for (auto & rdep : get_sched_info(t).m_reverse_deps) { switch (get_state(rdep).load()) { case task_state::Waiting: case task_state::Queued: if (check_deps(rdep)) { m_waiting.erase(rdep); if (get_state(rdep).load() < task_state::Running) { lean_always_assert(get_data(rdep)); // TODO(gabriel): we need to give up the lock on m_mutex for this if (false && get_data(rdep)->m_flags.m_eager_execution) { get_state(rdep) = task_state::Running; execute(rdep); handle_finished(rdep); } else { enqueue(rdep); } } } break; case task_state::Failed: // TODO(gabriel): removed failed tasks from reverse dependency lists? m_waiting.erase(rdep); break; case task_state::Success: // this can happen if a task occurs in more than one reverse dependency list, // or gets submitted more than once break; default: lean_unreachable(); } } clear(t); }
void MainGUI::start_populate_scene_thread() { boost::thread populate_scene_thread(boost::bind(&MainForm::populateScene, mf)); populate_scene_thread.join(); handle_finished(); }
void mt_task_queue::spawn_worker() { lean_always_assert(!m_shutting_down); auto this_worker = std::make_shared<worker_info>(); m_workers.push_back(this_worker); m_required_workers--; this_worker->m_thread.reset(new lthread([this, this_worker]() { save_stack_info(false); unique_lock<mutex> lock(m_mutex); while (true) { if (m_shutting_down) { break; } if (m_required_workers < 0) { scoped_add<int> inc_required(m_required_workers, +1); scoped_add<unsigned> inc_sleeping(m_sleeping_workers, +1); if (m_wake_up_worker.wait_for(lock, g_worker_max_idle_time, [&] { return m_required_workers >= 1 || m_shutting_down; })) { continue; } else { break; } } if (m_queue.empty()) { if (m_queue_added.wait_for(lock, g_worker_max_idle_time, [&] { return !m_queue.empty() || m_shutting_down; })) { continue; } else { break; } } auto t = dequeue(); if (get_state(t).load() != task_state::Queued) continue; get_state(t) = task_state::Running; reset_heartbeat(); { flet<gtask> _(this_worker->m_current_task, t); scoped_current_task scope_cur_task(&t); notify_queue_changed(); lock.unlock(); execute(t); lock.lock(); } reset_heartbeat(); handle_finished(t); notify_queue_changed(); } // We need to run the finalizers while the lock is held, // otherwise we risk a race condition at the end of the program. // We would finalize in the thread, while we call the finalize() function. run_thread_finalizers(); run_post_thread_finalizers(); m_workers.erase(std::find(m_workers.begin(), m_workers.end(), this_worker)); m_required_workers++; m_shut_down_cv.notify_all(); })); }