diff options
author | Brad Leege <bleege@gmail.com> | 2015-05-04 17:04:46 -0500 |
---|---|---|
committer | Brad Leege <bleege@gmail.com> | 2015-05-04 17:04:46 -0500 |
commit | 4ce4e979ff85f8fc135fccf675c6a5e8939cdd66 (patch) | |
tree | dd49fd5b095445d9ef2ff28ec64157bacbbe2dd5 /src/mbgl/util/thread.hpp | |
parent | 7f6cc6cc6d462952c02fbc50bd90f4f765a55809 (diff) | |
parent | c2858dd45f735d99b1bc46043cff0b2a6b176c63 (diff) | |
download | qtlocation-mapboxgl-4ce4e979ff85f8fc135fccf675c6a5e8939cdd66.tar.gz |
Updating from master
Diffstat (limited to 'src/mbgl/util/thread.hpp')
-rw-r--r-- | src/mbgl/util/thread.hpp | 65 |
1 files changed, 54 insertions, 11 deletions
diff --git a/src/mbgl/util/thread.hpp b/src/mbgl/util/thread.hpp index 4831b9efc2..e97872a502 100644 --- a/src/mbgl/util/thread.hpp +++ b/src/mbgl/util/thread.hpp @@ -3,9 +3,11 @@ #include <future> #include <thread> +#include <atomic> #include <functional> #include <mbgl/util/run_loop.hpp> +#include <mbgl/platform/platform.hpp> namespace { @@ -33,11 +35,16 @@ namespace util { // Thread<> constructor blocks until the thread and the Object are fully created, so after the // object creation, it's safe to obtain the Object stored in this thread. +enum class ThreadPriority : bool { + Regular, + Low, +}; + template <class Object> class Thread { public: template <class... Args> - Thread(const std::string& name, Args&&... args); + Thread(const std::string& name, ThreadPriority priority, Args&&... args); ~Thread(); // Invoke object->fn(args...) in the runloop thread. @@ -48,11 +55,33 @@ public: // Invoke object->fn(args...) in the runloop thread, then invoke callback(result) in the current thread. template <typename Fn, class R, class... Args> - void invokeWithResult(Fn fn, std::function<void (R)> callback, Args&&... args) { - loop->invokeWithResult(std::bind(fn, object, args...), callback); + void invokeWithResult(Fn fn, std::function<void (R)>&& callback, Args&&... args) { + loop->invokeWithResult(std::bind(fn, object, args...), std::move(callback)); + } + + // Invoke object->fn(args...) in the runloop thread, then invoke callback() in the current thread. + template <typename Fn, class... Args> + void invokeWithResult(Fn fn, std::function<void ()>&& callback, Args&&... args) { + loop->invokeWithResult(std::bind(fn, object, args...), std::move(callback)); + } + + // Invoke object->fn(args...) in the runloop thread, and wait for the result. + template <class R, typename Fn, class... Args> + R invokeSync(Fn fn, Args&&... args) { + std::packaged_task<R ()> task(std::bind(fn, object, args...)); + std::future<R> future = task.get_future(); + loop->invoke(std::move(task)); + return future.get(); } - uv_loop_t* get() { return loop->get(); } + // Invoke object->fn(args...) in the runloop thread, and wait for it to complete. + template <typename Fn, class... Args> + void invokeSync(Fn fn, Args&&... args) { + std::packaged_task<void ()> task(std::bind(fn, object, args...)); + std::future<void> future = task.get_future(); + loop->invoke(std::move(task)); + return future.get(); + } private: Thread(const Thread&) = delete; @@ -74,7 +103,7 @@ private: template <class Object> template <class... Args> -Thread<Object>::Thread(const std::string& name, Args&&... args) { +Thread<Object>::Thread(const std::string& name, ThreadPriority priority, Args&&... args) { // Note: We're using std::tuple<> to store the arguments because GCC 4.9 has a bug // when expanding parameters packs captured in lambdas. std::tuple<Args...> params = std::forward_as_tuple(::std::forward<Args>(args)...); @@ -86,6 +115,10 @@ Thread<Object>::Thread(const std::string& name, Args&&... args) { (void(name)); #endif + if (priority == ThreadPriority::Low) { + platform::makeThreadLowPriority(); + } + constexpr auto seq = typename integer_sequence<sizeof...(Args)>::type(); run(std::move(params), seq); }); @@ -96,14 +129,24 @@ Thread<Object>::Thread(const std::string& name, Args&&... args) { template <class Object> template <typename P, std::size_t... I> void Thread<Object>::run(P&& params, index_sequence<I...>) { - Object object_(std::get<I>(std::forward<P>(params))...); - object = &object_; + uv::loop l; + + { + RunLoop loop_(l.get()); + loop = &loop_; - RunLoop loop_; - loop = &loop_; + Object object_(l.get(), std::get<I>(std::forward<P>(params))...); + object = &object_; + + running.set_value(); + l.run(); + + loop = nullptr; + object = nullptr; + } - running.set_value(); - loop_.run(); + // Run the loop again to ensure that async close callbacks have been called. + l.run(); joinable.get_future().get(); } |