From 034551f1519491110b83f74662af7d4c0c509104 Mon Sep 17 00:00:00 2001 From: Ivo van Dongen Date: Fri, 21 Jul 2017 15:51:34 +0300 Subject: [core] make thread pause/resume thread safe --- include/mbgl/util/thread.hpp | 12 ++++++++---- test/util/thread.test.cpp | 33 +++++++++++++++++++++++++++++++++ 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 lock(pauseMutex); - assert(!paused); + if (paused) { + return; + } paused = std::make_unique>(); resumed = std::make_unique>(); @@ -116,9 +118,11 @@ public: // Resumes the `Object` thread previously paused by `pause()`. void resume() { - MBGL_VERIFY_THREAD(tid); + std::unique_lock 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 #include +#include 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 test("Test"); + + std::promise 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(); +} -- cgit v1.2.1