Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
[core] make thread pause/resume thread safe
Browse files Browse the repository at this point in the history
  • Loading branch information
ivovandongen committed Aug 14, 2017
1 parent 50bd7a1 commit 034551f
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 4 deletions.
12 changes: 8 additions & 4 deletions include/mbgl/util/thread.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,11 @@ class Thread : public Scheduler {
// 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>>();
Expand All @@ -116,9 +118,11 @@ class Thread : public Scheduler {

// 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();

Expand Down
33 changes: 33 additions & 0 deletions test/util/thread.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <atomic>
#include <memory>
#include <thread>

using namespace mbgl;
using namespace mbgl::util;
Expand Down Expand Up @@ -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();
}

0 comments on commit 034551f

Please sign in to comment.