[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.
This commit is contained in:
committed by
Thiago Marcos P. Santos
parent
465c949153
commit
86300ccedf
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user