From 1e55c332cda0a2baab2b6dc06286725a86c8e71e Mon Sep 17 00:00:00 2001 From: Leith Bade Date: Sun, 9 Nov 2014 23:52:34 +1100 Subject: [PATCH] Wait for pause Tidy up Remove red fill --- android/cpp/NativeMapView.cpp | 8 +-- android/cpp/NativeMapView.hpp | 2 +- include/mbgl/map/map.hpp | 5 +- src/map/map.cpp | 97 ++++++++++++++--------------------- 4 files changed, 47 insertions(+), 65 deletions(-) diff --git a/android/cpp/NativeMapView.cpp b/android/cpp/NativeMapView.cpp index d046642dd..40bf35a38 100644 --- a/android/cpp/NativeMapView.cpp +++ b/android/cpp/NativeMapView.cpp @@ -316,7 +316,7 @@ bool NativeMapView::createSurface(ANativeWindow* window_) { void NativeMapView::destroySurface() { LOG_VERBOSE("NativeMapView::destroySurface"); - pause(); + pause(true); if (surface != EGL_NO_SURFACE) { if (!eglDestroySurface(display, surface)) { @@ -518,13 +518,13 @@ void NativeMapView::stop() { } -void NativeMapView::pause() { - LOG_VERBOSE("NativeMapView::pause"); +void NativeMapView::pause(bool wait_for_pause) { + LOG_VERBOSE("NativeMapView::pause %s", (wait_for_pause) ? "true" : "false"); LOG_ASSERT(display != EGL_NO_DISPLAY); LOG_ASSERT(context != EGL_NO_CONTEXT); - map->pause(); + map->pause(wait_for_pause); } void NativeMapView::resume() { diff --git a/android/cpp/NativeMapView.hpp b/android/cpp/NativeMapView.hpp index 05aa11b88..7a7ad1817 100644 --- a/android/cpp/NativeMapView.hpp +++ b/android/cpp/NativeMapView.hpp @@ -63,7 +63,7 @@ public: void stop(); void resume(); - void pause(); + void pause(bool wait_for_pause = false); void notifyMapChange(); diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index 6dbcd3550..135811daa 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -178,9 +178,12 @@ private: private: bool terminating = false; + bool pausing = false; bool is_paused = false; + std::unique_ptr mutex_run; + std::unique_ptr cond_run; std::unique_ptr mutex_pause; - std::unique_ptr cond_resume; + std::unique_ptr cond_pause; private: // If cleared, the next time the render thread attempts to render the map, it will *actually* diff --git a/src/map/map.cpp b/src/map/map.cpp index 2de77cd3c..ba298c00e 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -36,8 +36,10 @@ Map::Map(View& view_) async_terminate(new uv_async_t()), async_render(new uv_async_t()), async_cleanup(new uv_async_t()), + mutex_run(std::make_unique()), + cond_run(std::make_unique()), mutex_pause(std::make_unique()), - cond_resume(std::make_unique()), + cond_pause(std::make_unique()), view(view_), #ifndef NDEBUG main_thread(uv_thread_self()), @@ -89,11 +91,6 @@ void Map::start(bool start_paused) { // Reset the flag. is_stopped = false; - // Do we need to pause first? - if (start_paused) { - pause(); - } - // Setup async notifications // Iron out the differences between libuv 0.10 and 0.11 @@ -117,6 +114,11 @@ void Map::start(bool start_paused) { #undef UV_ASYNC_CALLBACK + // Do we need to pause first? + if (start_paused) { + pause(); + } + uv_thread_create(*thread, [](void *arg) { Map *map = static_cast(arg); #ifndef NDEBUG @@ -167,42 +169,30 @@ void Map::stop(stop_callback cb, void *data) { void Map::pause(bool wait_for_pause) { assert(uv_thread_self() == main_thread); assert(async); - Log::Info(Event::General, "Map::pause() start"); + mutex_run->lock(); + pausing = true; + mutex_run->unlock(); - // TODO wait until paused before return - - - Log::Info(Event::General, "Map::pause() locking"); - mutex_pause->lock(); - Log::Info(Event::General, "Map::pause() locked"); - is_paused = true; - Log::Info(Event::General, "Map::pause() set is_paused = true"); - Log::Info(Event::General, "Map::pause() unlocking"); - mutex_pause->unlock(); - Log::Info(Event::General, "Map::pause() unlocked"); - - Log::Info(Event::General, "Map::pause() stopping loop"); uv_stop(**loop); - Log::Info(Event::General, "Map::pause() stopping done"); + rerender(); // Needed to ensure uv_stop is seen and uv_run exits, otherwise we deadlock on wait_for_pause + + if (wait_for_pause) { + mutex_pause->lock(); + while (!is_paused) { + cond_pause->wait(*mutex_pause); + } + mutex_pause->unlock(); + } } void Map::resume() { assert(uv_thread_self() == main_thread); assert(async); - Log::Info(Event::General, "Map::resume() start"); - - Log::Info(Event::General, "Map::resume() locking"); - mutex_pause->lock(); - Log::Info(Event::General, "Map::resume() locked"); - is_paused = false; - Log::Info(Event::General, "Map::resume() set is_paused = false"); - Log::Info(Event::General, "Map::resume() broadcasting"); - cond_resume->broadcast(); - Log::Info(Event::General, "Map::resume() broadcasted"); - Log::Info(Event::General, "Map::resume() unlocking"); - mutex_pause->unlock(); - Log::Info(Event::General, "Map::resume() unlocked"); - Log::Info(Event::General, "Map::resume() done"); + + mutex_run->lock(); + pausing = false; + cond_run->broadcast(); + mutex_run->unlock(); } void Map::run() { @@ -218,24 +208,12 @@ void Map::run() { setup(); prepare(); - Log::Info(Event::General, "Map::run() start"); terminating = false; - Log::Info(Event::General, "Map::run() set terminating = false"); - - Log::Info(Event::General, "Map::run() entering run loop"); while(!terminating) { - Log::Info(Event::General, "Map::run() next run loop, terminating = %s", terminating ? "true" : "false"); - Log::Info(Event::General, "Map::run() uv_run enter"); uv_run(**loop, UV_RUN_DEFAULT); - Log::Info(Event::General, "Map::run() exit"); - check_for_pause(); - - //uv_run(**loop, UV_RUN_DEFAULT); } - Log::Info(Event::General, "Map::run() run loop exit"); - // Run the event loop once more to make sure our async delete handlers are called. uv_run(**loop, UV_RUN_ONCE); @@ -250,20 +228,21 @@ void Map::run() { } void Map::check_for_pause() { - Log::Info(Event::General, "Map::check_for_pause() locking"); - mutex_pause->lock(); - Log::Info(Event::General, "Map::check_for_pause() locked"); - Log::Info(Event::General, "Map::check_for_pause() entering pause loop"); - while (is_paused) { - Log::Info(Event::General, "Map::check_for_pause() next pause loop, is_paused = %s", is_paused ? "true" : "false"); - Log::Info(Event::General, "Map::check_for_pause() waiting"); - cond_resume->wait(*mutex_pause); - Log::Info(Event::General, "Map::check_for_pause() waited"); + mutex_run->lock(); + while (pausing) { + mutex_pause->lock(); + is_paused = true; + cond_pause->broadcast(); + mutex_pause->unlock(); + + cond_run->wait(*mutex_run); } - Log::Info(Event::General, "Map::check_for_pause() exit pause loop"); - Log::Info(Event::General, "Map::check_for_pause() unlocking"); + + mutex_pause->lock(); + is_paused = false; mutex_pause->unlock(); - Log::Info(Event::General, "Map::check_for_pause() unlocked"); + + mutex_run->unlock(); } void Map::rerender() {