summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThiago Marcos P. Santos <thiago@mapbox.com>2017-02-24 15:05:28 +0200
committerThiago Marcos P. Santos <tmpsantos@gmail.com>2017-02-25 14:03:38 +0200
commit86300ccedfc5ccdace551ce76f9185513d736127 (patch)
treefe64868fd13243bfc0e240cf3ce8690c8947c266 /src
parent465c949153a838bb3159204ab268eb551fbd2e6c (diff)
downloadqtlocation-mapboxgl-86300ccedfc5ccdace551ce76f9185513d736127.tar.gz
[core] Add pause/resume to the Thread class
Make a thread completely halt and not process any message on the message queue until resume() is called. Sending a sync message to a halted thread will result on a deadlock, thus the assertion. Deleting a paused thread will trigger a resume.
Diffstat (limited to 'src')
-rw-r--r--src/mbgl/util/thread.hpp45
1 files changed, 45 insertions, 0 deletions
diff --git a/src/mbgl/util/thread.hpp b/src/mbgl/util/thread.hpp
index b03c7f3e7c..184c6a8a12 100644
--- a/src/mbgl/util/thread.hpp
+++ b/src/mbgl/util/thread.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include <cassert>
#include <future>
#include <thread>
#include <atomic>
@@ -9,6 +10,7 @@
#include <mbgl/util/run_loop.hpp>
#include <mbgl/util/thread_context.hpp>
#include <mbgl/util/platform.hpp>
+#include <mbgl/util/util.hpp>
namespace mbgl {
namespace util {
@@ -47,6 +49,8 @@ public:
// Invoke object->fn(args...) asynchronously, but wait for the result.
template <typename Fn, class... Args>
auto invokeSync(Fn fn, Args&&... args) {
+ assert(!paused);
+
using R = std::result_of_t<Fn(Object, Args&&...)>;
std::packaged_task<R ()> task(std::bind(fn, object, args...));
std::future<R> future = task.get_future();
@@ -54,7 +58,39 @@ public:
return future.get();
}
+ void pause() {
+ MBGL_VERIFY_THREAD(tid);
+
+ assert(!paused);
+
+ paused = std::make_unique<std::promise<void>>();
+ resumed = std::make_unique<std::promise<void>>();
+
+ auto pausing = paused->get_future();
+
+ loop->invoke([this] {
+ auto resuming = resumed->get_future();
+ paused->set_value();
+ resuming.get();
+ });
+
+ pausing.get();
+ }
+
+ void resume() {
+ MBGL_VERIFY_THREAD(tid);
+
+ assert(paused);
+
+ resumed->set_value();
+
+ resumed.reset();
+ paused.reset();
+ }
+
private:
+ MBGL_STORE_THREAD(tid);
+
Thread(const Thread&) = delete;
Thread(Thread&&) = delete;
Thread& operator=(const Thread&) = delete;
@@ -73,6 +109,9 @@ private:
std::promise<void> running;
std::promise<void> joinable;
+ std::unique_ptr<std::promise<void>> paused;
+ std::unique_ptr<std::promise<void>> resumed;
+
std::thread thread;
Object* object = nullptr;
@@ -119,6 +158,12 @@ void Thread<Object>::run(P&& params, std::index_sequence<I...>) {
template <class Object>
Thread<Object>::~Thread() {
+ MBGL_VERIFY_THREAD(tid);
+
+ if (paused) {
+ resume();
+ }
+
loop->stop();
joinable.set_value();
thread.join();