Commit af5ec753 authored by Giuseppe Ottaviano's avatar Giuseppe Ottaviano Committed by Facebook Github Bot

Add support for getting other threads' names

Summary: Complete the `ThreadName.h` API.

Reviewed By: luciang, Orvid

Differential Revision: D5289160

fbshipit-source-id: a48e61093008039da50b1c568364fa5b8744b401
parent fc91e303
......@@ -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<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
......@@ -59,11 +81,11 @@ bool canSetOtherThreadName() {
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 (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()));
......@@ -72,23 +94,16 @@ Optional<std::string> getCurrentThreadName() {
#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
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 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
......
......@@ -25,24 +25,42 @@
#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
* 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();
/**
* 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);
}
......@@ -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);
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment