Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions realtime_tools/include/realtime_tools/async_function_handler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ class AsyncSchedulingPolicy
* the async callback method. If true, the async callback method will not be called until the trigger predicate
* returns true for the first time. Very useful when the type is DETACHED.
* @param print_warnings Whether to print warnings when the async callback method is not triggered due to any reason.
* @param thread_name The custom name for the async thread. Defaults to the component name. Will be truncated to 15 characters.
*/
struct AsyncFunctionHandlerParams
{
Expand Down Expand Up @@ -178,6 +179,7 @@ struct AsyncFunctionHandlerParams
* before starting the async callback method. Default is true.
* - print_warnings (bool): Whether to print warnings when the async callback method is not triggered
* due to any reason. Default is true.
* - thread_name (string): Name applied to the async thread. Defaults to component name. Truncated to 15 chars.
* @param node The node that is used to get the parameters.
* @param prefix Parameter prefix to use when accessing node parameters.
*/
Expand Down Expand Up @@ -216,6 +218,9 @@ struct AsyncFunctionHandlerParams
if (node->has_parameter(prefix + "print_warnings")) {
print_warnings = node->get_parameter(prefix + "print_warnings").as_bool();
}
if (node->has_parameter(prefix + "thread_name")) {
thread_name = node->get_parameter(prefix + "thread_name").as_string();
}
}

int thread_priority = 50;
Expand All @@ -227,6 +232,7 @@ struct AsyncFunctionHandlerParams
std::function<bool()> trigger_predicate = []() { return true; };
bool wait_until_initial_trigger = true;
bool print_warnings = true;
std::string thread_name = "";
};

/**
Expand Down Expand Up @@ -566,6 +572,17 @@ class AsyncFunctionHandler
params_.logger, affinity_result.first,
"Async worker thread is successfully pinned to the requested CPU cores!");
}
if (!params_.thread_name.empty()) {
const auto rename_result = realtime_tools::set_current_thread_name(params_.thread_name);

if (!rename_result.first) {
RCLCPP_WARN(
params_.logger, "Could not set thread name for the async worker thread. Error: %s",
rename_result.second.c_str());
} else {
RCLCPP_INFO(params_.logger, "%s", rename_result.second.c_str());
}
}
if (params_.scheduling_policy == AsyncSchedulingPolicy::SYNCHRONIZED) {
execute_synchronized_callback();
} else {
Expand Down
9 changes: 9 additions & 0 deletions realtime_tools/include/realtime_tools/realtime_helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,15 @@ std::pair<bool, std::string> set_current_thread_affinity(int core);
*/
std::pair<bool, std::string> set_current_thread_affinity(const std::vector<int> & cores);

/**
* Configure the current thread name.
* \param[in] name The name for the thread.
* On Linux, it will be automatically truncated to 15 characters.
* \returns a pair of a boolean indicating whether the operation succeeded or not
* and a message describing the result of the operation
*/
std::pair<bool, std::string> set_current_thread_name(const std::string & name);

/**
* Method to get the amount of available cpu cores
* \ref https://man7.org/linux/man-pages/man3/sysconf.3.html
Expand Down
33 changes: 33 additions & 0 deletions realtime_tools/src/realtime_helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,39 @@ std::pair<bool, std::string> set_current_thread_affinity(const std::vector<int>
#endif
}

std::pair<bool, std::string> set_current_thread_name(const std::string & name)
{
if (name.empty()) {
return std::make_pair(false, "Thread name cannot be empty. This should not happen!");
}

#ifdef _WIN32
std::wstring wname(name.begin(), name.end());
HRESULT hr = SetThreadDescription(GetCurrentThread(), wname.c_str());
if (SUCCEEDED(hr)) {
return std::make_pair(true, "Thread name: " + name);
}
return std::make_pair(false, "Failed to set thread name on Windows.");
#elif defined(__APPLE__)
std::string t_name = name.substr(0, 63);
std::string msg =
(name.length() > 63) ? "Thread name (truncated): " + t_name : "Thread name: " + t_name;
if (pthread_setname_np(t_name.c_str()) == 0) {
return std::make_pair(true, msg);
}
return std::make_pair(false, "Failed to set thread name on macOS.");
#else
std::string t_name = name.substr(0, 15);
std::string msg =
(name.length() > 15) ? "Thread name (truncated): " + t_name : "Thread name: " + t_name;
int rc = pthread_setname_np(pthread_self(), t_name.c_str());
if (rc == 0) {
return std::make_pair(true, msg);
}
return std::make_pair(false, "Failed to set thread name. Error code: " + std::to_string(rc));
#endif
}

int64_t get_number_of_available_processors()
{
#ifdef _WIN32
Expand Down
Loading