#include "drape_frontend/scenario_manager.hpp" #include "drape_frontend/user_event_stream.hpp" namespace df { ScenarioManager::ScenarioManager(FrontendRenderer * frontendRenderer) : m_frontendRenderer(frontendRenderer) , m_needInterrupt(false) , m_isFinished(false) { ASSERT(m_frontendRenderer != nullptr, ()); } ScenarioManager::~ScenarioManager() { std::lock_guard lock(m_mutex); if (m_thread != nullptr) { m_thread->join(); m_thread.reset(); } } void ScenarioManager::Interrupt() { std::lock_guard lock(m_mutex); InterruptImpl(); } bool ScenarioManager::RunScenario(ScenarioData && scenarioData, ScenarioCallback const & onStartFn, ScenarioCallback const & onFinishFn) { std::lock_guard lock(m_mutex); if (m_thread != nullptr) { if (m_isFinished) InterruptImpl(); else return false; // The only scenario can be executed currently. } std::swap(m_scenarioData, scenarioData); m_onStartHandler = onStartFn; m_onFinishHandler = onFinishFn; m_thread = my::make_unique(&ScenarioManager::ThreadRoutine, this); #ifdef DEBUG m_threadId = m_thread->get_id(); #endif return true; } bool ScenarioManager::IsRunning() { std::lock_guard lock(m_mutex); if (m_thread == nullptr) return false; if (m_isFinished) { InterruptImpl(); return false; } return true; } void ScenarioManager::ThreadRoutine() { string const scenarioName = m_scenarioData.m_name; if (m_onStartHandler != nullptr) m_onStartHandler(scenarioName); for (auto const & action : m_scenarioData.m_scenario) { // Interrupt scenario if it's necessary. { std::lock_guard lock(m_mutex); if (m_needInterrupt) { m_needInterrupt = false; break; } } switch(action->GetType()) { case ActionType::CenterViewport: { CenterViewportAction * centerViewportAction = static_cast(action.get()); m_frontendRenderer->AddUserEvent(make_unique_dp(centerViewportAction->GetCenter(), centerViewportAction->GetZoomLevel(), true /* isAnim */, false /* trackVisibleViewport */)); break; } case ActionType::WaitForTime: { WaitForTimeAction * waitForTimeAction = static_cast(action.get()); std::this_thread::sleep_for(waitForTimeAction->GetDuration()); break; } default: LOG(LINFO, ("Unknown action in scenario")); } } ScenarioCallback handler = nullptr; { std::lock_guard lock(m_mutex); m_scenarioData.m_scenario.clear(); m_isFinished = true; if (m_onFinishHandler != nullptr) { handler = m_onFinishHandler; m_onFinishHandler = nullptr; } } if (handler != nullptr) handler(scenarioName); } void ScenarioManager::InterruptImpl() { if (m_thread == nullptr) return; ASSERT_NOT_EQUAL(m_threadId, std::this_thread::get_id(), ()); if (m_isFinished) { m_thread->join(); m_thread.reset(); m_isFinished = false; m_needInterrupt = false; } else { m_needInterrupt = true; } } } // namespace df