option to pass data parameter, and add more explanation
This commit is contained in:
@@ -183,7 +183,9 @@ int GLFWView::run() {
|
||||
glfwWaitEvents();
|
||||
}
|
||||
|
||||
map->stop(glfwWaitEvents);
|
||||
map->stop([](void *) {
|
||||
glfwWaitEvents();
|
||||
});
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user