From af5ec753ebabe7de1fc021951edd61d0f49d15a8 Mon Sep 17 00:00:00 2001 From: Giuseppe Ottaviano Date: Tue, 20 Jun 2017 23:03:57 -0700 Subject: [PATCH] Add support for getting other threads' names Summary: Complete the `ThreadName.h` API. Reviewed By: luciang, Orvid Differential Revision: D5289160 fbshipit-source-id: a48e61093008039da50b1c568364fa5b8744b401 --- folly/ThreadName.cpp | 44 ++++++++++++++++++++++++----------- folly/ThreadName.h | 20 +++++++++++++++- folly/test/ThreadNameTest.cpp | 38 +++++++++++------------------- 3 files changed, 62 insertions(+), 40 deletions(-) diff --git a/folly/ThreadName.cpp b/folly/ThreadName.cpp index 22ead209..6f311575 100644 --- a/folly/ThreadName.cpp +++ b/folly/ThreadName.cpp @@ -40,6 +40,28 @@ namespace folly { #endif #endif +namespace { + +#if FOLLY_HAVE_PTHREAD +pthread_t stdTidToPthreadId(std::thread::id tid) { + static_assert( + std::is_same::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 @@ -59,11 +81,11 @@ bool canSetOtherThreadName() { static constexpr size_t kMaxThreadNameLength = 16; -Optional getCurrentThreadName() { +Optional getThreadName(std::thread::id id) { #if FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME || \ FOLLY_HAS_PTHREAD_SETNAME_NP_NAME std::array 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(); } return make_optional(std::string(buf.data())); @@ -72,23 +94,16 @@ Optional getCurrentThreadName() { #endif } +Optional getCurrentThreadName() { + return getThreadName(std::this_thread::get_id()); +} + bool setThreadName(std::thread::id tid, StringPiece name) { #if !FOLLY_HAVE_PTHREAD || _WIN32 return false; #else - static_assert( - std::is_same::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 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 @@ -99,6 +114,7 @@ bool setThreadName(std::thread::id tid, StringPiece name) { } return false; #else + (void)id; return false; #endif #endif diff --git a/folly/ThreadName.h b/folly/ThreadName.h index d78e2fa1..ba7bde25 100644 --- a/folly/ThreadName.h +++ b/folly/ThreadName.h @@ -25,24 +25,42 @@ #include 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 * 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 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 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 + +/** + * Equivalent to setThreadName(std::this_thread::get_id(), name); + */ bool setThreadName(StringPiece name); } diff --git a/folly/test/ThreadNameTest.cpp b/folly/test/ThreadNameTest.cpp index b804bbb1..d47416b3 100644 --- a/folly/test/ThreadNameTest.cpp +++ b/folly/test/ThreadNameTest.cpp @@ -24,27 +24,24 @@ 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) { - static constexpr StringPiece kThreadName{"rockin-thread"}; thread th([] { EXPECT_EQ(expectedSetSelfThreadNameResult, setThreadName(kThreadName)); if (expectedSetSelfThreadNameResult) { - EXPECT_EQ(kThreadName.toString(), getCurrentThreadName().value()); + EXPECT_EQ(kThreadName.toString(), *getCurrentThreadName()); } }); 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; @@ -58,19 +55,7 @@ TEST(ThreadName, setThreadName_other_pthread) { 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) { @@ -82,5 +67,8 @@ TEST(ThreadName, setThreadName_other_id) { 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); + } } -- 2.34.1