diff options
author | Konstantin Käfer <mail@kkaefer.com> | 2014-09-17 15:39:16 +0200 |
---|---|---|
committer | Konstantin Käfer <mail@kkaefer.com> | 2014-09-24 16:14:10 +0200 |
commit | 111fccb76c1f599470074a75ca77e9de016cca73 (patch) | |
tree | efda4dfe3cc787d3907730ffb11d3e2795f8b510 | |
parent | ba18c08524cffd3fa03adf49f680f3a80390d61d (diff) | |
download | qtlocation-mapboxgl-111fccb76c1f599470074a75ca77e9de016cca73.tar.gz |
option to pass data parameter, and add more explanation
-rw-r--r-- | common/glfw_view.cpp | 4 | ||||
-rw-r--r-- | include/mbgl/map/map.hpp | 13 | ||||
-rw-r--r-- | src/map/map.cpp | 15 |
3 files changed, 25 insertions, 7 deletions
diff --git a/common/glfw_view.cpp b/common/glfw_view.cpp index fb54d55f39..edfb3a6a6f 100644 --- a/common/glfw_view.cpp +++ b/common/glfw_view.cpp @@ -183,7 +183,9 @@ int GLFWView::run() { glfwWaitEvents(); } - map->stop(glfwWaitEvents); + map->stop([](void *) { + glfwWaitEvents(); + }); return 0; } diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index 48c4e89cc9..85c9e8e6a5 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -31,16 +31,21 @@ class FileSource; class View; class Map : private util::noncopyable { - typedef void (*stop_callback)(); + typedef void (*stop_callback)(void *); public: explicit Map(View &view); ~Map(); - // Start/stop the map render thread. the start() call is asynchronous, while the stop() call - // will block until the map rendering thread stopped. + // Start the map render thread. It is asynchronous. void start(); - void stop(stop_callback cb = nullptr); + + // Stop the map render thread. This call will block until the map rendering thread stopped. + // The optional callback function will be invoked repeatedly until the map thread is stopped. + // The callback function should wait until it is woken up again by view.notify(), otherwise + // this will be a busy waiting loop. The optional data parameter will be passed to the callback + // function. + void stop(stop_callback cb = nullptr, void *data = nullptr); // Runs the map event loop. ONLY run this function when you want to get render a single frame // with this map object. It will *not* spawn a separate thread and instead block until the diff --git a/src/map/map.cpp b/src/map/map.cpp index b1a7b1c2fd..eabf7b8fe8 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -100,11 +100,14 @@ void Map::start() { #ifndef NDEBUG map->map_thread = -1; #endif + + // Make sure that the stop() function knows when to stop invoking the callback function. map->is_stopped = true; + map->view.notify(); }, this); } -void Map::stop(stop_callback cb) { +void Map::stop(stop_callback cb, void *data) { assert(uv_thread_self() == main_thread); assert(main_thread != map_thread); assert(async); @@ -112,11 +115,19 @@ void Map::stop(stop_callback cb) { uv_async_send(async_terminate.get()); if (cb) { + // Wait until the render thread stopped. We are using this construct instead of plainly + // relying on the thread_join because the system might need to run things in the current + // thread that is required for the render thread to terminate correctly. This is for example + // the case with Cocoa's NSURLRequest. Otherwise, we will eventually deadlock because this + // thread (== main thread) is blocked. The callback function should use an efficient waiting + // function to avoid a busy waiting loop. while (!is_stopped) { - cb(); + cb(data); } } + // If a callback function was provided, this should return immediately because the thread has + // already finished executing. uv_thread_join(*thread); async = false; |