diff options
author | Konstantin Käfer <mail@kkaefer.com> | 2014-09-16 18:23:42 +0200 |
---|---|---|
committer | Konstantin Käfer <mail@kkaefer.com> | 2014-09-24 16:14:09 +0200 |
commit | fd2b2e208229259630f92bd7615f9197c163d27f (patch) | |
tree | 48cc7012e05c9c09e4bf437e0bab6598025e3f55 /src | |
parent | f26bb724dc164b69b5358f30c6248fdf5cbd076b (diff) | |
download | qtlocation-mapboxgl-fd2b2e208229259630f92bd7615f9197c163d27f.tar.gz |
use separate workers for tile parsing to avoid blocking the threadpool for other libuv actions
Diffstat (limited to 'src')
-rw-r--r-- | src/map/map.cpp | 8 | ||||
-rw-r--r-- | src/map/tile_data.cpp | 2 | ||||
-rw-r--r-- | src/storage/sqlite_store.cpp | 2 | ||||
-rw-r--r-- | src/util/uv-channel.c | 14 | ||||
-rw-r--r-- | src/util/uv-worker.c | 41 |
5 files changed, 59 insertions, 8 deletions
diff --git a/src/map/map.cpp b/src/map/map.cpp index ecf4eb2837..93e1bea536 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -60,6 +60,13 @@ Map::~Map() { } } +uv::worker &Map::getWorker() { + if (!workers) { + workers = std::make_unique<uv::worker>(**loop, 4, "Tile Worker"); + } + return *workers; +} + void Map::start() { assert(uv_thread_self() == main_thread); assert(!async); @@ -198,6 +205,7 @@ void Map::terminate(uv_async_t *async) { map->glyphStore.reset(); map->fileSource.reset(); map->style.reset(); + map->workers.reset(); map->activeSources.clear(); uv_close((uv_handle_t *)map->async_cleanup.get(), nullptr); diff --git a/src/map/tile_data.cpp b/src/map/tile_data.cpp index 2a0e96cad6..ecb05d5b26 100644 --- a/src/map/tile_data.cpp +++ b/src/map/tile_data.cpp @@ -87,7 +87,7 @@ void TileData::reparse() { // We're creating a new work request. The work request deletes itself after it executed // the after work handler new uv::work<util::ptr<TileData>>( - map.getLoop(), + map.getWorker(), [](util::ptr<TileData> &tile) { tile->parse(); }, diff --git a/src/storage/sqlite_store.cpp b/src/storage/sqlite_store.cpp index baa599eef9..d44520a95e 100644 --- a/src/storage/sqlite_store.cpp +++ b/src/storage/sqlite_store.cpp @@ -32,7 +32,7 @@ SQLiteStore::SQLiteStore(uv_loop_t *loop, const std::string &path) db(std::make_shared<Database>(path.c_str(), ReadWrite | Create)) { createSchema(); worker = new uv_worker_t; - uv_worker_init_named(worker, loop, "SQLite"); + uv_worker_init(worker, loop, 1, "SQLite"); } SQLiteStore::~SQLiteStore() { diff --git a/src/util/uv-channel.c b/src/util/uv-channel.c index 3d0483fd70..2936b01c53 100644 --- a/src/util/uv-channel.c +++ b/src/util/uv-channel.c @@ -49,7 +49,21 @@ void *uv_chan_receive(uv_chan_t *chan) { return data; } +void uv_chan_clear(uv_chan_t *chan) { + uv_mutex_lock(&chan->mutex); + uv__chan_item_t *item = NULL; + QUEUE *head = NULL; + while (!QUEUE_EMPTY(&chan->q)) { + head = QUEUE_HEAD(&chan->q); + item = QUEUE_DATA(head, uv__chan_item_t, active_queue); + QUEUE_REMOVE(head); + free(item); + } + uv_mutex_unlock(&chan->mutex); +} + void uv_chan_destroy(uv_chan_t *chan) { + uv_chan_clear(chan); uv_cond_destroy(&chan->cond); uv_mutex_destroy(&chan->mutex); } diff --git a/src/util/uv-worker.c b/src/util/uv-worker.c index d0e2550b73..c47b0ffed2 100644 --- a/src/util/uv-worker.c +++ b/src/util/uv-worker.c @@ -1,5 +1,6 @@ #include <mbgl/util/uv-worker.h> #include <mbgl/util/uv-messenger.h> +#include <mbgl/util/queue.h> #include <stdio.h> @@ -10,6 +11,12 @@ struct uv__worker_item_s { uv_worker_after_cb after_work_cb; }; +typedef struct uv__work_thread_s uv__work_thread_t; +struct uv__work_thread_s { + uv_thread_t thread; + void *queue[2]; +}; + void uv__worker_after(void *ptr) { uv__worker_item_t *item = (uv__worker_item_t *)ptr; item->after_work_cb(item->data); @@ -30,20 +37,29 @@ void uv__worker_thread_loop(void *ptr) { item->work_cb(item->data); uv_messenger_send(worker->msgr, item); } -} -int uv_worker_init(uv_worker_t *worker, uv_loop_t *loop) { - return uv_worker_init_named(worker, loop, NULL); + // Make sure to close all other workers too. + uv_chan_send(&worker->chan, NULL); } -int uv_worker_init_named(uv_worker_t *worker, uv_loop_t *loop, const char *name) { +int uv_worker_init(uv_worker_t *worker, uv_loop_t *loop, int count, const char *name) { worker->name = name; worker->msgr = malloc(sizeof(uv_messenger_t)); int ret = uv_messenger_init(loop, worker->msgr, uv__worker_after); if (ret < 0) return ret; ret = uv_chan_init(&worker->chan); if (ret < 0) return ret; - return uv_thread_create(&worker->thread, uv__worker_thread_loop, worker); + + // Initialize worker threads. + QUEUE_INIT(&worker->threads); + for (int i = 0; i < count; i++) { + uv__work_thread_t *work_thread = malloc(sizeof(uv__work_thread_t)); + ret = uv_thread_create(&work_thread->thread, uv__worker_thread_loop, worker); + if (ret < 0) return ret; + QUEUE_INSERT_TAIL(&worker->threads, &work_thread->queue); + } + + return 0; } void uv_worker_send(uv_worker_t *worker, void *data, uv_worker_cb work_cb, @@ -55,8 +71,21 @@ void uv_worker_send(uv_worker_t *worker, void *data, uv_worker_cb work_cb, uv_chan_send(&worker->chan, item); } +void uv_worker_join_all(uv_worker_t *worker) { + QUEUE *head = NULL; + uv__work_thread_t *item = NULL; + while (!QUEUE_EMPTY(&worker->threads)) { + head = QUEUE_HEAD(&worker->threads); + item = QUEUE_DATA(head, uv__work_thread_t, queue); + QUEUE_REMOVE(head); + uv_thread_join(&item->thread); + free(item); + } +} + void uv_worker_close(uv_worker_t *worker) { uv_chan_send(&worker->chan, NULL); - uv_thread_join(&worker->thread); + uv_worker_join_all(worker); + uv_chan_destroy(&worker->chan); uv_messenger_stop(worker->msgr); } |