diff options
author | Konstantin Käfer <mail@kkaefer.com> | 2015-04-10 15:36:32 +0200 |
---|---|---|
committer | Konstantin Käfer <mail@kkaefer.com> | 2015-04-10 15:36:32 +0200 |
commit | bba3d9838a512c75a63f5eb9263913ec96011e8d (patch) | |
tree | afe1462c6e134fffae55fceaae45a8920e63644b /src | |
parent | 8eafe36932c3c5407a305268bc5b62e70ad8b8b0 (diff) | |
download | qtlocation-mapboxgl-bba3d9838a512c75a63f5eb9263913ec96011e8d.tar.gz |
add Thread<T> and RunLoop
Thread<T> is a generic thread management object that starts a thread, creates an object T in that thread and calls its .start() function. When the Thread<T> object is destructed (which must happen in the thread that created it), it'll call the object's .stop() function, and wait for thread termination. The .stop() function must somehow get the thread to terminate. Note that object T's constructor/destructor/start()/stop() must be protected/private, and Thread<T> must be declared as a friend class. All public functions may be called from any thread and are exposed through operator->().
RunLoop encapsulates a libuv runloop and has a facility of dispatching function objects to the thread. It can be used either as a worker thread class by itself, or it can be derived from. This commit converts SQLiteCache to derive from RunLoop and removes the custom code used previously for managing the cache thread.
Diffstat (limited to 'src')
-rw-r--r-- | src/mbgl/storage/default_file_source.cpp | 6 | ||||
-rw-r--r-- | src/mbgl/util/run_loop.cpp | 55 | ||||
-rw-r--r-- | src/mbgl/util/uv_detail.hpp | 19 |
3 files changed, 74 insertions, 6 deletions
diff --git a/src/mbgl/storage/default_file_source.cpp b/src/mbgl/storage/default_file_source.cpp index ca8d423b1b..841a56bcef 100644 --- a/src/mbgl/storage/default_file_source.cpp +++ b/src/mbgl/storage/default_file_source.cpp @@ -122,11 +122,7 @@ Request *DefaultFileSource::request(const Resource &resource, uv_loop_t *l, cons void DefaultFileSource::request(const Resource &resource, const Environment &env, Callback callback) { - auto req = new Request(resource, nullptr, env, std::move(callback)); - - // This function can be called from any thread. Make sure we're executing the actual call in the - // file source loop by sending it over the queue. It will be processed in processAction(). - queue->send(AddRequestAction{ req }); + request(resource, nullptr, env, std::move(callback)); } void DefaultFileSource::cancel(Request *req) { diff --git a/src/mbgl/util/run_loop.cpp b/src/mbgl/util/run_loop.cpp new file mode 100644 index 0000000000..3a7cf597ff --- /dev/null +++ b/src/mbgl/util/run_loop.cpp @@ -0,0 +1,55 @@ +#include <mbgl/util/run_loop.hpp> +#include <mbgl/util/uv_detail.hpp> +#include <mbgl/util/std.hpp> + +#include <uv.h> + +namespace /* anonymous */ { +inline void critical_section(std::mutex& mutex, std::function<void()> fn) { + std::lock_guard<std::mutex> lock(mutex); + fn(); +} +} + +namespace mbgl { +namespace util { + +RunLoop::RunLoop() + : runloop(util::make_unique<uv::loop>()), + runloopAsync(util::make_unique<uv::async>(runloop->get(), std::bind(&RunLoop::process, this))) { +} + +// Define here since we can't destroy the uv::* objects from just the header file. +RunLoop::~RunLoop() = default; + +void RunLoop::start() { + runloop->run(); +} + +void RunLoop::stop() { + critical_section(runloopMutex, [this] { runloopQueue.push(nullptr); }); + runloopAsync->send(); +} + +void RunLoop::process() { + std::queue<std::function<void()>> queue; + critical_section(runloopMutex, [this, &queue] { queue.swap(runloopQueue); }); + while (!queue.empty()) { + if (queue.front()) { + queue.front()(); + } else { + runloopAsync->unref(); + } + queue.pop(); + } +} + +void RunLoop::invoke(std::function<void()> fn) { + if (fn) { + critical_section(runloopMutex, [this, &fn] { runloopQueue.push(fn); }); + runloopAsync->send(); + } +} + +} +} diff --git a/src/mbgl/util/uv_detail.hpp b/src/mbgl/util/uv_detail.hpp index 9d479da425..6acef1b386 100644 --- a/src/mbgl/util/uv_detail.hpp +++ b/src/mbgl/util/uv_detail.hpp @@ -41,10 +41,19 @@ public: uv_loop_close(l); delete l; #endif + } + + inline void run() { + uv_run(l, UV_RUN_DEFAULT); + } + inline uv_loop_t* operator*() { + return l; } - inline uv_loop_t *operator*() { return l; } + inline uv_loop_t* get() { + return l; + } private: uv_loop_t *l = nullptr; @@ -72,6 +81,14 @@ public: } } + inline void ref() { + uv_ref(reinterpret_cast<uv_handle_t*>(a.get())); + } + + inline void unref() { + uv_unref(reinterpret_cast<uv_handle_t*>(a.get())); + } + private: #if UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR <= 10 static void async_cb(uv_async_t* a, int) { |