summaryrefslogtreecommitdiff
path: root/src/mbgl/util/thread.hpp
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2015-04-20 18:28:10 -0700
committerJohn Firebaugh <john.firebaugh@gmail.com>2015-04-28 14:32:22 -0400
commit75ae956b0e598685117f7f72231677d8841cbea3 (patch)
tree0aadbd3927d2ff5f57a7da8710ef644acaa4ba5b /src/mbgl/util/thread.hpp
parent32c818feea8af1a355c661978694382245854413 (diff)
downloadqtlocation-mapboxgl-75ae956b0e598685117f7f72231677d8841cbea3.tar.gz
WIP: Use Thread<MapContext>
Diffstat (limited to 'src/mbgl/util/thread.hpp')
-rw-r--r--src/mbgl/util/thread.hpp51
1 files changed, 47 insertions, 4 deletions
diff --git a/src/mbgl/util/thread.hpp b/src/mbgl/util/thread.hpp
index 956e7718dc..036ac33c97 100644
--- a/src/mbgl/util/thread.hpp
+++ b/src/mbgl/util/thread.hpp
@@ -3,6 +3,7 @@
#include <future>
#include <thread>
+#include <atomic>
#include <functional>
#include <mbgl/util/run_loop.hpp>
@@ -52,6 +53,29 @@ public:
loop->invokeWithResult(std::bind(fn, object, args...), 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::promise<R> promise;
+ auto bound = std::bind(fn, object, args...);
+ loop->invoke([&] { promise.set_value(bound()); } );
+ return promise.get_future().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::promise<void> promise;
+ auto bound = std::bind(fn, object, args...);
+ loop->invoke([&] { bound(); promise.set_value(); } );
+ promise.get_future().get();
+ }
+
+ // Join the thread, but call the given function repeatedly in the current thread
+ // while waiting for the join to finish. This should be immediately followed by
+ // destroying the Thread.
+ void pumpingStop(std::function<void ()>);
+
uv_loop_t* get() { return loop->get(); }
private:
@@ -67,6 +91,7 @@ private:
std::promise<void> joinable;
std::thread thread;
+ std::atomic_bool joined;
Object* object;
RunLoop* loop;
@@ -74,7 +99,8 @@ private:
template <class Object>
template <class... Args>
-Thread<Object>::Thread(const std::string& name, Args&&... args) {
+Thread<Object>::Thread(const std::string& name, Args&&... args)
+ : joined(false) {
// 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)...);
@@ -99,13 +125,21 @@ void Thread<Object>::run(P&& params, index_sequence<I...>) {
RunLoop loop_;
loop = &loop_;
- Object object_(loop_.get(), std::get<I>(std::forward<P>(params))...);
- object = &object_;
+ {
+ Object object_(loop_.get(), std::get<I>(std::forward<P>(params))...);
+ object = &object_;
- running.set_value();
+ running.set_value();
+ loop_.run();
+
+ object = nullptr;
+ }
+
+ // Run the loop again to ensure that async close callbacks have been called.
loop_.run();
joinable.get_future().get();
+ joined = true;
}
template <class Object>
@@ -115,6 +149,15 @@ Thread<Object>::~Thread() {
thread.join();
}
+template <class Object>
+void Thread<Object>::pumpingStop(std::function<void ()> cb) {
+ loop->stop();
+ joinable.set_value();
+ while (!joined) {
+ cb();
+ }
+}
+
}
}