diff options
author | Thiago Marcos P. Santos <thiago@mapbox.com> | 2017-02-24 15:05:28 +0200 |
---|---|---|
committer | Thiago Marcos P. Santos <tmpsantos@gmail.com> | 2017-02-25 14:03:38 +0200 |
commit | 86300ccedfc5ccdace551ce76f9185513d736127 (patch) | |
tree | fe64868fd13243bfc0e240cf3ce8690c8947c266 /src/mbgl | |
parent | 465c949153a838bb3159204ab268eb551fbd2e6c (diff) | |
download | qtlocation-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/mbgl')
-rw-r--r-- | src/mbgl/util/thread.hpp | 45 |
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(); |