summaryrefslogtreecommitdiff
path: root/src/mbgl/util/thread.hpp
diff options
context:
space:
mode:
authorBrad Leege <bleege@gmail.com>2015-05-04 17:04:46 -0500
committerBrad Leege <bleege@gmail.com>2015-05-04 17:04:46 -0500
commit4ce4e979ff85f8fc135fccf675c6a5e8939cdd66 (patch)
treedd49fd5b095445d9ef2ff28ec64157bacbbe2dd5 /src/mbgl/util/thread.hpp
parent7f6cc6cc6d462952c02fbc50bd90f4f765a55809 (diff)
parentc2858dd45f735d99b1bc46043cff0b2a6b176c63 (diff)
downloadqtlocation-mapboxgl-4ce4e979ff85f8fc135fccf675c6a5e8939cdd66.tar.gz
Updating from master
Diffstat (limited to 'src/mbgl/util/thread.hpp')
-rw-r--r--src/mbgl/util/thread.hpp65
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();
}