add a callback to stop() to allow running the current thread's event loop

This commit is contained in:
Konstantin Käfer
2014-09-17 15:29:24 +02:00
parent 89cd310cf6
commit ba18c08524
5 changed files with 26 additions and 3 deletions

View File

@@ -183,7 +183,7 @@ int GLFWView::run() {
glfwWaitEvents();
}
map->stop();
map->stop(glfwWaitEvents);
return 0;
}
@@ -192,6 +192,10 @@ void GLFWView::make_active() {
glfwMakeContextCurrent(window);
}
void GLFWView::notify() {
glfwPostEmptyEvent();
}
void GLFWView::swap() {
glfwPostEmptyEvent();

View File

@@ -17,6 +17,7 @@ public:
void initialize(mbgl::Map *map);
void swap();
void make_active();
void notify();
void notify_map_change(mbgl::MapChange change, mbgl::timestamp delay = 0);
static void key(GLFWwindow *window, int key, int scancode, int action, int mods);

View File

@@ -31,6 +31,8 @@ class FileSource;
class View;
class Map : private util::noncopyable {
typedef void (*stop_callback)();
public:
explicit Map(View &view);
~Map();
@@ -38,7 +40,7 @@ public:
// Start/stop the map render thread. the start() call is asynchronous, while the stop() call
// will block until the map rendering thread stopped.
void start();
void stop();
void stop(stop_callback cb = 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
@@ -179,6 +181,9 @@ private:
// ready for rendering.
std::atomic_flag is_rendered = ATOMIC_FLAG_INIT;
// Stores whether the map thread has been stopped already.
std::atomic_bool is_stopped;
public:
View &view;

View File

@@ -41,6 +41,8 @@ public:
return 0;
}
virtual void notify() = 0;
// Notifies a watcher of map x/y/scale/rotation changes.
// Must only be called from the same thread that caused the change.
// Must not be called from the render thread.

View File

@@ -75,6 +75,9 @@ void Map::start() {
// updated rendering. Only in these cases, we attach the async handlers.
async = true;
// Reset the flag.
is_stopped = false;
// Setup async notifications
uv_async_init(**loop, async_terminate.get(), terminate);
async_terminate->data = this;
@@ -97,15 +100,23 @@ void Map::start() {
#ifndef NDEBUG
map->map_thread = -1;
#endif
map->is_stopped = true;
}, this);
}
void Map::stop() {
void Map::stop(stop_callback cb) {
assert(uv_thread_self() == main_thread);
assert(main_thread != map_thread);
assert(async);
uv_async_send(async_terminate.get());
if (cb) {
while (!is_stopped) {
cb();
}
}
uv_thread_join(*thread);
async = false;