summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvo van Dongen <info@ivovandongen.nl>2017-07-21 15:51:34 +0300
committerIvo van Dongen <info@ivovandongen.nl>2017-08-14 23:10:09 +0300
commit034551f1519491110b83f74662af7d4c0c509104 (patch)
tree62caaf5cd42d0189a26af298a474919108142eff
parent50bd7a112663d247bc453c205f6fcdb6759e7dde (diff)
downloadqtlocation-mapboxgl-034551f1519491110b83f74662af7d4c0c509104.tar.gz
[core] make thread pause/resume thread safe
-rw-r--r--include/mbgl/util/thread.hpp12
-rw-r--r--test/util/thread.test.cpp33
2 files changed, 41 insertions, 4 deletions
diff --git a/include/mbgl/util/thread.hpp b/include/mbgl/util/thread.hpp
index 572f46080e..06254569a9 100644
--- a/include/mbgl/util/thread.hpp
+++ b/include/mbgl/util/thread.hpp
@@ -96,9 +96,11 @@ public:
// sent to a paused `Object` will be queued and only processed after
// `resume()` is called.
void pause() {
- MBGL_VERIFY_THREAD(tid);
+ std::unique_lock<std::mutex> lock(pauseMutex);
- assert(!paused);
+ if (paused) {
+ return;
+ }
paused = std::make_unique<std::promise<void>>();
resumed = std::make_unique<std::promise<void>>();
@@ -116,9 +118,11 @@ public:
// Resumes the `Object` thread previously paused by `pause()`.
void resume() {
- MBGL_VERIFY_THREAD(tid);
+ std::unique_lock<std::mutex> lock(pauseMutex);
- assert(paused);
+ if (!paused) {
+ return;
+ }
resumed->set_value();
diff --git a/test/util/thread.test.cpp b/test/util/thread.test.cpp
index 76fb5ce3f0..228e463d9e 100644
--- a/test/util/thread.test.cpp
+++ b/test/util/thread.test.cpp
@@ -7,6 +7,7 @@
#include <atomic>
#include <memory>
+#include <thread>
using namespace mbgl;
using namespace mbgl::util;
@@ -275,3 +276,35 @@ TEST(Thread, PauseResume) {
thread.actor().invoke(&TestWorker::send, [&] { loop.stop(); });
loop.run();
}
+
+TEST(Thread, PauseResumeMultiThreaded) {
+ RunLoop loop;
+
+ // Thread to be paused
+ Thread<TestWorker> test("Test");
+
+ std::promise<void> thread1Complete;
+ auto future = thread1Complete.get_future();
+ std::thread thread1 {[&, promise = std::move(thread1Complete)]() mutable {
+ // Pause the thread
+ test.pause();
+ promise.set_value();
+ }};
+
+ // Wait for the test thread to be paused
+ future.wait();
+
+ std::thread thread2 {[&]() {
+ // Pause from this thread as well and resume
+ test.pause();
+ test.resume();
+ }};
+
+ // Queue a message at the end of test thread's queue.
+ test.actor().invoke(&TestWorker::send, [&] { loop.stop(); });
+ loop.run();
+
+ // Wait for threads
+ thread1.join();
+ thread2.join();
+}