Add support for getting other threads' names
authorGiuseppe Ottaviano <ott@fb.com>
Wed, 21 Jun 2017 06:03:57 +0000 (23:03 -0700)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Wed, 21 Jun 2017 06:06:01 +0000 (23:06 -0700)
Summary: Complete the `ThreadName.h` API.

Reviewed By: luciang, Orvid

Differential Revision: D5289160

fbshipit-source-id: a48e61093008039da50b1c568364fa5b8744b401

folly/ThreadName.cpp
folly/ThreadName.h
folly/test/ThreadNameTest.cpp

index 22ead20917e83f9ab58255c333b37eab3b437cdf..6f3115758e000ee10cf6f79e1b090862306d3890 100644 (file)
@@ -40,6 +40,28 @@ namespace folly {
 #endif
 #endif
 
 #endif
 #endif
 
+namespace {
+
+#if FOLLY_HAVE_PTHREAD
+pthread_t stdTidToPthreadId(std::thread::id tid) {
+  static_assert(
+      std::is_same<pthread_t, std::thread::native_handle_type>::value,
+      "This assumes that the native handle type is pthread_t");
+  static_assert(
+      sizeof(std::thread::native_handle_type) == sizeof(std::thread::id),
+      "This assumes std::thread::id is a thin wrapper around "
+      "std::thread::native_handle_type, but that doesn't appear to be true.");
+  // In most implementations, std::thread::id is a thin wrapper around
+  // std::thread::native_handle_type, which means we can do unsafe things to
+  // extract it.
+  pthread_t id;
+  std::memcpy(&id, &tid, sizeof(id));
+  return id;
+}
+#endif
+
+} // namespace
+
 bool canSetCurrentThreadName() {
 #if FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME || \
     FOLLY_HAS_PTHREAD_SETNAME_NP_NAME
 bool canSetCurrentThreadName() {
 #if FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME || \
     FOLLY_HAS_PTHREAD_SETNAME_NP_NAME
@@ -59,11 +81,11 @@ bool canSetOtherThreadName() {
 
 static constexpr size_t kMaxThreadNameLength = 16;
 
 
 static constexpr size_t kMaxThreadNameLength = 16;
 
-Optional<std::string> getCurrentThreadName() {
+Optional<std::string> getThreadName(std::thread::id id) {
 #if FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME || \
     FOLLY_HAS_PTHREAD_SETNAME_NP_NAME
   std::array<char, kMaxThreadNameLength> buf;
 #if FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME || \
     FOLLY_HAS_PTHREAD_SETNAME_NP_NAME
   std::array<char, kMaxThreadNameLength> buf;
-  if (pthread_getname_np(pthread_self(), buf.data(), buf.size()) != 0) {
+  if (pthread_getname_np(stdTidToPthreadId(id), buf.data(), buf.size()) != 0) {
     return Optional<std::string>();
   }
   return make_optional(std::string(buf.data()));
     return Optional<std::string>();
   }
   return make_optional(std::string(buf.data()));
@@ -72,23 +94,16 @@ Optional<std::string> getCurrentThreadName() {
 #endif
 }
 
 #endif
 }
 
+Optional<std::string> getCurrentThreadName() {
+  return getThreadName(std::this_thread::get_id());
+}
+
 bool setThreadName(std::thread::id tid, StringPiece name) {
 #if !FOLLY_HAVE_PTHREAD || _WIN32
   return false;
 #else
 bool setThreadName(std::thread::id tid, StringPiece name) {
 #if !FOLLY_HAVE_PTHREAD || _WIN32
   return false;
 #else
-  static_assert(
-      std::is_same<pthread_t, std::thread::native_handle_type>::value,
-      "This assumes that the native handle type is pthread_t");
-  static_assert(
-      sizeof(std::thread::native_handle_type) == sizeof(std::thread::id),
-      "This assumes std::thread::id is a thin wrapper around "
-      "std::thread::native_handle_type, but that doesn't appear to be true.");
-  // In most implementations, std::thread::id is a thin wrapper around
-  // std::thread::native_handle_type, which means we can do unsafe things to
-  // extract it.
-  pthread_t id;
-  std::memcpy(&id, &tid, sizeof(id));
   auto trimmedName = name.fbstr().substr(0, kMaxThreadNameLength - 1);
   auto trimmedName = name.fbstr().substr(0, kMaxThreadNameLength - 1);
+  auto id = stdTidToPthreadId(tid);
 #if FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME
   return 0 == pthread_setname_np(id, trimmedName.c_str());
 #elif FOLLY_HAS_PTHREAD_SETNAME_NP_NAME
 #if FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME
   return 0 == pthread_setname_np(id, trimmedName.c_str());
 #elif FOLLY_HAS_PTHREAD_SETNAME_NP_NAME
@@ -99,6 +114,7 @@ bool setThreadName(std::thread::id tid, StringPiece name) {
   }
   return false;
 #else
   }
   return false;
 #else
+  (void)id;
   return false;
 #endif
 #endif
   return false;
 #endif
 #endif
index d78e2fa17a5430e52ca67664dcb3b676210aef2d..ba7bde25953925e451fdc447af422643365edacd 100644 (file)
 #include <folly/portability/PThread.h>
 
 namespace folly {
 #include <folly/portability/PThread.h>
 
 namespace folly {
+
 /**
  * This returns true if the current platform supports setting the name of the
  * current thread.
  */
 bool canSetCurrentThreadName();
 /**
  * This returns true if the current platform supports setting the name of the
  * current thread.
  */
 bool canSetCurrentThreadName();
+
 /**
  * This returns true if the current platform supports setting the name of
  * threads other than the one currently executing.
  */
 bool canSetOtherThreadName();
 /**
  * This returns true if the current platform supports setting the name of
  * threads other than the one currently executing.
  */
 bool canSetOtherThreadName();
+
+/**
+ * Get the name of the given thread, or nothing if an error occurs
+ * or the functionality is not available.
+ */
+Optional<std::string> getThreadName(std::thread::id tid);
+
 /**
 /**
- * Get the name of the current string, or nothing if an error occurs.
+ * Equivalent to getThreadName(std::this_thread::get_id());
  */
 Optional<std::string> getCurrentThreadName();
 
  */
 Optional<std::string> getCurrentThreadName();
 
+/**
+ * Set the name of the given thread.
+ * Returns false on failure, if an error occurs or the functionality
+ * is not available.
+ */
 bool setThreadName(std::thread::id tid, StringPiece name);
 #if FOLLY_HAVE_PTHREAD
 bool setThreadName(pthread_t pid, StringPiece name);
 #endif
 bool setThreadName(std::thread::id tid, StringPiece name);
 #if FOLLY_HAVE_PTHREAD
 bool setThreadName(pthread_t pid, StringPiece name);
 #endif
+
+/**
+ * Equivalent to setThreadName(std::this_thread::get_id(), name);
+ */
 bool setThreadName(StringPiece name);
 }
 bool setThreadName(StringPiece name);
 }
index b804bbb156c3dfa5ae6cd2a4f6cc1ac1c677edca..d47416b3ffab256f5f86e4cb44a87881ea82cf27 100644 (file)
 using namespace std;
 using namespace folly;
 
 using namespace std;
 using namespace folly;
 
-static bool expectedSetOtherThreadNameResult = folly::canSetOtherThreadName();
-static bool expectedSetSelfThreadNameResult = folly::canSetCurrentThreadName();
+namespace {
+
+const bool expectedSetOtherThreadNameResult = folly::canSetOtherThreadName();
+const bool expectedSetSelfThreadNameResult = folly::canSetCurrentThreadName();
+constexpr StringPiece kThreadName{"rockin-thread"};
+
+} // namespace
 
 TEST(ThreadName, getCurrentThreadName) {
 
 TEST(ThreadName, getCurrentThreadName) {
-  static constexpr StringPiece kThreadName{"rockin-thread"};
   thread th([] {
     EXPECT_EQ(expectedSetSelfThreadNameResult, setThreadName(kThreadName));
     if (expectedSetSelfThreadNameResult) {
   thread th([] {
     EXPECT_EQ(expectedSetSelfThreadNameResult, setThreadName(kThreadName));
     if (expectedSetSelfThreadNameResult) {
-      EXPECT_EQ(kThreadName.toString(), getCurrentThreadName().value());
+      EXPECT_EQ(kThreadName.toString(), *getCurrentThreadName());
     }
   });
   SCOPE_EXIT { th.join(); };
 }
 
     }
   });
   SCOPE_EXIT { th.join(); };
 }
 
-TEST(ThreadName, setThreadName_self) {
-  thread th([] {
-    EXPECT_EQ(expectedSetSelfThreadNameResult, setThreadName("rockin-thread"));
-  });
-  SCOPE_EXIT { th.join(); };
-}
-
 TEST(ThreadName, setThreadName_other_pthread) {
   Baton<> handle_set;
   Baton<> let_thread_end;
 TEST(ThreadName, setThreadName_other_pthread) {
   Baton<> handle_set;
   Baton<> let_thread_end;
@@ -58,19 +55,7 @@ TEST(ThreadName, setThreadName_other_pthread) {
   handle_set.wait();
   SCOPE_EXIT { let_thread_end.post(); };
   EXPECT_EQ(
   handle_set.wait();
   SCOPE_EXIT { let_thread_end.post(); };
   EXPECT_EQ(
-      expectedSetOtherThreadNameResult, setThreadName(handle, "rockin-thread"));
-}
-
-TEST(ThreadName, setThreadName_other_native) {
-  Baton<> let_thread_end;
-  thread th([&] {
-      let_thread_end.wait();
-  });
-  SCOPE_EXIT { th.join(); };
-  SCOPE_EXIT { let_thread_end.post(); };
-  EXPECT_EQ(
-      expectedSetOtherThreadNameResult,
-      setThreadName(th.native_handle(), "rockin-thread"));
+      expectedSetOtherThreadNameResult, setThreadName(handle, kThreadName));
 }
 
 TEST(ThreadName, setThreadName_other_id) {
 }
 
 TEST(ThreadName, setThreadName_other_id) {
@@ -82,5 +67,8 @@ TEST(ThreadName, setThreadName_other_id) {
   SCOPE_EXIT { let_thread_end.post(); };
   EXPECT_EQ(
       expectedSetOtherThreadNameResult,
   SCOPE_EXIT { let_thread_end.post(); };
   EXPECT_EQ(
       expectedSetOtherThreadNameResult,
-      setThreadName(th.get_id(), "rockin-thread"));
+      setThreadName(th.get_id(), kThreadName));
+  if (expectedSetOtherThreadNameResult) {
+    EXPECT_EQ(*getThreadName(th.get_id()), kThreadName);
+  }
 }
 }