[llvm] r256087 - ThreadPool unittest: reimplement concurrency test, deterministically this time.
Vedant Kumar via llvm-commits
llvm-commits at lists.llvm.org
Fri Dec 18 22:30:08 PST 2015
Thanks :).
> +
> + /// Make sure this thread not progress faster than the main thread.
> + void waitForMainThread() {
> + while (!MainThreadReady) {
> + std::unique_lock<std::mutex> LockGuard(WaitMainThreadMutex);
> + WaitMainThread.wait(LockGuard, [&] { return MainThreadReady; });
Nit: wait(CV, Predicate) is guaranteed to not wake up spuriously. The surrounding while loop here is redundant.
> + }
> + }
> + std::condition_variable WaitMainThread;
> + std::mutex WaitMainThreadMutex;
> + bool MainThreadReady;
> +
> };
>
> #define CHECK_UNSUPPORTED() \
> @@ -68,12 +80,17 @@ TEST_F(ThreadPoolTest, AsyncBarrier) {
>
> std::atomic_int checked_in{0};
>
> + MainThreadReady = false;
> ThreadPool Pool;
> for (size_t i = 0; i < 5; ++i) {
> - Pool.async([&checked_in, i] {
> + Pool.async([this, &checked_in, i] {
> + waitForMainThread();
> ++checked_in;
> });
> }
> + ASSERT_EQ(0, checked_in);
> + MainThreadReady = true;
Paranoid nit: Can this assignment be reordered before the assert? If so, the main thread could context-switch to an async worker that's awake. Later, the assert will fail. Wdyt of changing this to --
void setMainThreadReadyState(bool Ready) {
std::unique_lock<std::mutex> LockGuard(WaitMainThreadMutex);
MainThreadReady = Ready;
}
setMainThreadReadyState(true);
That should still test the async behavior.
vedant
> + WaitMainThread.notify_all();
> Pool.wait();
> ASSERT_EQ(5, checked_in);
> }
> @@ -97,10 +114,15 @@ TEST_F(ThreadPoolTest, Async) {
> CHECK_UNSUPPORTED();
> ThreadPool Pool;
> std::atomic_int i{0};
> - Pool.async([&i] {
> + MainThreadReady = false;
> + Pool.async([this, &i] {
> + waitForMainThread();
> ++i;
> });
> Pool.async([&i] { ++i; });
> + ASSERT_NE(2, i.load());
> + MainThreadReady = true;
> + WaitMainThread.notify_all();
> Pool.wait();
> ASSERT_EQ(2, i.load());
> }
> @@ -109,11 +131,16 @@ TEST_F(ThreadPoolTest, GetFuture) {
> CHECK_UNSUPPORTED();
> ThreadPool Pool;
> std::atomic_int i{0};
> - Pool.async([&i] {
> + MainThreadReady = false;
> + Pool.async([this, &i] {
> + waitForMainThread();
> ++i;
> });
> // Force the future using get()
> Pool.async([&i] { ++i; }).get();
> + ASSERT_NE(2, i.load());
> + MainThreadReady = true;
> + WaitMainThread.notify_all();
> Pool.wait();
> ASSERT_EQ(2, i.load());
> }
> @@ -122,14 +149,18 @@ TEST_F(ThreadPoolTest, PoolDestruction)
> CHECK_UNSUPPORTED();
> // Test that we are waiting on destruction
> std::atomic_int checked_in{0};
> -
> {
> + MainThreadReady = false;
> ThreadPool Pool;
> for (size_t i = 0; i < 5; ++i) {
> - Pool.async([&checked_in, i] {
> + Pool.async([this, &checked_in, i] {
> + waitForMainThread();
> ++checked_in;
> });
> }
> + ASSERT_EQ(0, checked_in);
> + MainThreadReady = true;
> + WaitMainThread.notify_all();
> }
> ASSERT_EQ(5, checked_in);
> }
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list