From f119ef798b9d6d5bac78148472e783428f27447a Mon Sep 17 00:00:00 2001
From: ReinUsesLisp <reinuseslisp@airmail.cc>
Date: Wed, 26 Aug 2020 01:41:46 +0000
Subject: [PATCH] common/thread: Fix data race in is_set

As report by tsan, Event::Set can write is_set while WaitFor and friends
are reading from it. To address this issue, make is_set an atomic.
---
 src/common/thread.h | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/src/common/thread.h b/src/common/thread.h
index 52b3594131..a8c17c71ab 100644
--- a/src/common/thread.h
+++ b/src/common/thread.h
@@ -4,6 +4,7 @@
 
 #pragma once
 
+#include <atomic>
 #include <chrono>
 #include <condition_variable>
 #include <cstddef>
@@ -25,13 +26,13 @@ public:
 
     void Wait() {
         std::unique_lock lk{mutex};
-        condvar.wait(lk, [&] { return is_set; });
+        condvar.wait(lk, [&] { return is_set.load(); });
         is_set = false;
     }
 
     bool WaitFor(const std::chrono::nanoseconds& time) {
         std::unique_lock lk{mutex};
-        if (!condvar.wait_for(lk, time, [this] { return is_set; }))
+        if (!condvar.wait_for(lk, time, [this] { return is_set.load(); }))
             return false;
         is_set = false;
         return true;
@@ -40,7 +41,7 @@ public:
     template <class Clock, class Duration>
     bool WaitUntil(const std::chrono::time_point<Clock, Duration>& time) {
         std::unique_lock lk{mutex};
-        if (!condvar.wait_until(lk, time, [this] { return is_set; }))
+        if (!condvar.wait_until(lk, time, [this] { return is_set.load(); }))
             return false;
         is_set = false;
         return true;
@@ -54,9 +55,9 @@ public:
     }
 
 private:
-    bool is_set = false;
     std::condition_variable condvar;
     std::mutex mutex;
+    std::atomic_bool is_set{false};
 };
 
 class Barrier {