summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2015-04-16 13:40:14 -0700
committerJohn Firebaugh <john.firebaugh@gmail.com>2015-05-21 19:57:28 -0700
commitb304b20073556d442764696dbe5ac09d5462ada0 (patch)
tree5f71825286162b893691874f3b0c72e0ea986f24 /src
parentd8274639a8a7a57bf11bac2e0c2b13b02c636bd4 (diff)
downloadqtlocation-mapboxgl-b304b20073556d442764696dbe5ac09d5462ada0.tar.gz
Add Thread tests; get argument transfer working for all cases
Diffstat (limited to 'src')
-rw-r--r--src/mbgl/util/run_loop.hpp69
-rw-r--r--src/mbgl/util/thread.hpp40
2 files changed, 57 insertions, 52 deletions
diff --git a/src/mbgl/util/run_loop.hpp b/src/mbgl/util/run_loop.hpp
index ed2b364cef..068215a04e 100644
--- a/src/mbgl/util/run_loop.hpp
+++ b/src/mbgl/util/run_loop.hpp
@@ -6,6 +6,7 @@
#include <mbgl/util/uv_detail.hpp>
#include <functional>
+#include <utility>
#include <queue>
#include <mutex>
@@ -19,37 +20,38 @@ public:
void stop();
- // Invoke fn() in the runloop thread.
- template <class Fn>
- void invoke(Fn&& fn) {
- auto invokable = util::make_unique<Invoker<Fn>>(std::move(fn));
+ // Invoke fn(args...) on this RunLoop.
+ template <class Fn, class... Args>
+ void invoke(Fn&& fn, Args&&... args) {
+ auto tuple = std::make_tuple(std::move(args)...);
+ auto invokable = util::make_unique<Invoker<Fn, decltype(tuple), Args...>>(std::move(fn), std::move(tuple));
withMutex([&] { queue.push(std::move(invokable)); });
async.send();
}
- // Invoke fn() in the runloop thread, then invoke callback(result) in the current thread.
- template <class Fn, class R>
- void invokeWithResult(Fn&& fn, std::function<void (R)>&& callback) {
- RunLoop* outer = current.get();
- assert(outer);
-
- invoke([fn = std::move(fn), callback = std::move(callback), outer] () mutable {
- outer->invoke([callback = std::move(callback), result = std::move(fn())] () mutable {
- callback(std::move(result));
- });
- });
+ // Return a function that invokes the given function on this RunLoop.
+ template <class... Args>
+ auto bind(std::function<void (Args...)> fn) {
+ return [this, fn = std::move(fn)] (Args&&... args) {
+ invoke(std::move(fn), std::move(args)...);
+ };
}
- // Invoke fn() in the runloop thread, then invoke callback() in the current thread.
- template <class Fn>
- void invokeWithResult(Fn&& fn, std::function<void ()>&& callback) {
- RunLoop* outer = current.get();
- assert(outer);
+ // Invoke fn(args...) on this RunLoop, then invoke callback(result) on the current RunLoop.
+ template <class R, class Fn, class... Args>
+ void invokeWithResult(Fn&& fn, std::function<void (R)> callback, Args&&... args) {
+ invoke([fn = std::move(fn), callback = current.get()->bind(callback)] (Args&&... a) mutable {
+ callback(fn(std::forward<Args>(a)...));
+ }, std::forward<Args>(args)...);
+ }
- invoke([fn = std::move(fn), callback = std::move(callback), outer] () mutable {
- fn();
- outer->invoke(std::move(callback));
- });
+ // Invoke fn(args...) on this RunLoop, then invoke callback() on the current RunLoop.
+ template <class Fn, class... Args>
+ void invokeWithResult(Fn&& fn, std::function<void ()> callback, Args&&... args) {
+ invoke([fn = std::move(fn), callback = current.get()->bind(callback)] (Args&&... a) mutable {
+ fn(std::forward<Args>(a)...);
+ callback();
+ }, std::forward<Args>(args)...);
}
uv_loop_t* get() { return async.get()->loop; }
@@ -65,11 +67,24 @@ private:
virtual ~Message() = default;
};
- template <class F>
+ template <class F, class P, class... Args>
struct Invoker : Message {
- Invoker(F&& f) : func(std::move(f)) {}
- void operator()() override { func(); }
+ Invoker(F&& f, P&& p)
+ : func(std::move(f)),
+ params(std::move(p)) {
+ }
+
+ void operator()() override {
+ invoke(std::index_sequence_for<Args...>{});
+ }
+
+ template <std::size_t... I>
+ void invoke(std::index_sequence<I...>) {
+ func(std::forward<Args>(std::get<I>(params))...);
+ }
+
F func;
+ P params;
};
using Queue = std::queue<std::unique_ptr<Message>>;
diff --git a/src/mbgl/util/thread.hpp b/src/mbgl/util/thread.hpp
index a2ad958645..f3a9baa6f3 100644
--- a/src/mbgl/util/thread.hpp
+++ b/src/mbgl/util/thread.hpp
@@ -4,26 +4,12 @@
#include <future>
#include <thread>
#include <atomic>
+#include <utility>
#include <functional>
#include <mbgl/util/run_loop.hpp>
#include <mbgl/platform/platform.hpp>
-namespace {
-
-template <::std::size_t...>
-struct index_sequence {};
-
-template <::std::size_t N, ::std::size_t... I>
-struct integer_sequence : integer_sequence<N - 1, N - 1, I...> {};
-
-template <::std::size_t... I>
-struct integer_sequence<0, I...> {
- using type = index_sequence<I...>;
-};
-
-}
-
namespace mbgl {
namespace util {
@@ -50,19 +36,19 @@ public:
// Invoke object->fn(args...) in the runloop thread.
template <typename Fn, class... Args>
void invoke(Fn fn, Args&&... args) {
- loop->invoke(std::bind(fn, object, args...));
+ loop->invoke(bind<Fn, Args...>(fn), std::forward<Args>(args)...);
}
// 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, std::move(args)...), std::move(callback));
+ template <class R, typename Fn, class... Args>
+ void invokeWithResult(Fn fn, std::function<void (R)> callback, Args&&... args) {
+ loop->invokeWithResult(bind<Fn, Args...>(fn), callback, std::forward<Args>(args)...);
}
// 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, std::move(args)...), std::move(callback));
+ void invokeWithResult(Fn fn, std::function<void ()> callback, Args&&... args) {
+ loop->invokeWithResult(bind<Fn, Args...>(fn), callback, std::forward<Args>(args)...);
}
// Invoke object->fn(args...) in the runloop thread, and wait for the result.
@@ -89,8 +75,13 @@ private:
Thread& operator=(const Thread&) = delete;
Thread& operator=(Thread&&) = delete;
+ template <typename Fn, class... Args>
+ auto bind(Fn fn) {
+ return [fn, this] (Args&&... a) { return (object->*fn)(std::forward<Args>(a)...); };
+ }
+
template <typename P, std::size_t... I>
- void run(P&& params, index_sequence<I...>);
+ void run(P&& params, std::index_sequence<I...>);
std::promise<void> running;
std::promise<void> joinable;
@@ -119,8 +110,7 @@ Thread<Object>::Thread(const std::string& name, ThreadPriority priority, Args&&.
platform::makeThreadLowPriority();
}
- constexpr auto seq = typename integer_sequence<sizeof...(Args)>::type();
- run(std::move(params), seq);
+ run(std::move(params), std::index_sequence_for<Args...>{});
});
running.get_future().get();
@@ -128,7 +118,7 @@ Thread<Object>::Thread(const std::string& name, ThreadPriority priority, Args&&.
template <class Object>
template <typename P, std::size_t... I>
-void Thread<Object>::run(P&& params, index_sequence<I...>) {
+void Thread<Object>::run(P&& params, std::index_sequence<I...>) {
uv::loop l;
{