add Thread::TryJoin
Change-Id: Idcd3aee2670a9c17fc38f60e9c07244478b69729
diff --git a/aos/common/util/thread.cc b/aos/common/util/thread.cc
index bfb1f51..54a8ef2 100644
--- a/aos/common/util/thread.cc
+++ b/aos/common/util/thread.cc
@@ -1,6 +1,7 @@
#include "aos/common/util/thread.h"
#include <pthread.h>
+#include <signal.h>
#include "aos/common/logging/logging.h"
@@ -10,9 +11,7 @@
Thread::Thread() : started_(false), joined_(false), should_terminate_(false) {}
Thread::~Thread() {
- if (started_ && !joined_) {
- CHECK(false);
- }
+ CHECK(!(started_ && !joined_));
}
void Thread::Start() {
@@ -28,6 +27,40 @@
CHECK(pthread_join(thread_, NULL) == 0);
}
+bool Thread::TryJoin() {
+ CHECK(!joined_ && started_);
+#ifdef AOS_SANITIZER_thread
+ // ThreadSanitizer misses the tryjoin and then complains about leaking the
+ // thread. Instead, we'll just check if the thread is still around and then
+ // do a regular Join() iff it isn't.
+ // TODO(brians): Remove this once tsan learns about pthread_tryjoin_np.
+ const int kill_ret = pthread_kill(thread_, 0);
+ // If it's still around.
+ if (kill_ret == 0) return false;
+ // If it died, we'll get ESRCH. Otherwise, something went wrong.
+ if (kill_ret != ESRCH) {
+ PELOG(FATAL, kill_ret, "pthread_kill(thread_, 0) failed");
+ }
+ Join();
+ return true;
+#else
+ const int ret = pthread_tryjoin_np(thread_, nullptr);
+ if (ret == 0) {
+ joined_ = true;
+ return true;
+ } else if (ret == EBUSY) {
+ return false;
+ } else {
+ PELOG(FATAL, ret, "pthread_tryjoin_np(thread_, nullptr) failed");
+ }
+#endif
+}
+
+void Thread::RequestStop() {
+ CHECK(!joined_ && started_);
+ should_terminate_.store(true);
+}
+
void Thread::WaitUntilDone() {
CHECK(!joined_ && started_);
joined_ = true;