1919#include < cwchar>
2020#elif defined TARGET_OS_MAC
2121#include < pthread.h>
22+ #include < mach/mach.h>
23+ #include < mach/thread_policy.h>
24+ #include < signal.h>
25+ #include < atomic>
26+ #include < chrono>
2227#elif defined __linux__ || defined __unix__
2328#include < sched.h>
2429#include < pthread.h>
@@ -92,53 +97,68 @@ Result set_name([[maybe_unused]] auto& handle, const char* name) {
9297 FreeLibrary (lib);
9398
9499#elif defined TARGET_OS_MAC
95- auto ret = pthread_setname_np (name);
100+ // On macOS, we use a signal-based mechanism to request the target thread to name itself.
101+ pthread_t threadHandle = handle;
96102
97- if (ret) {
98- throw std::runtime_error (" Unable to set thread name, error code" + std::to_string (ret));
103+ // Define a static flag (of type volatile sig_atomic_t) that the signal handler will set.
104+ static volatile sig_atomic_t nameSetFlag = 0 ;
105+
106+ static const char * desiredThreadName = name;
107+
108+ // Define the signal handler
109+ const auto threadNameHandler = +[](int /* signum*/ ) -> void {
110+ if (desiredThreadName != nullptr ) {
111+ pthread_setname_np (desiredThreadName);
112+ }
113+ nameSetFlag = 1 ; // Feed-back Flag
114+ };
115+
116+ // Install the signal handler once for the process.
117+ static std::atomic_flag handlerInstalled = ATOMIC_FLAG_INIT;
118+ if (!handlerInstalled.test_and_set (std::memory_order_acquire)) {
119+ signal (SIGUSR1, threadNameHandler);
120+ }
121+
122+ // Send SIGUSR1 to the target thread so it runs our signal handler.
123+ if (pthread_kill (threadHandle, SIGUSR1) != 0 ) {
124+ return Result::unsupported;
99125 }
126+
127+ // Wait until the flag is set. Instead of sleeping for a fixed time,
128+ auto start = std::chrono::steady_clock::now ();
129+ while (nameSetFlag == 0 ) {std::this_thread::yield ();} // yield to reduce CPU usage
130+
131+ return Result::ok;
132+
100133#elif defined __linux__ || defined __unix__
101134 auto ret = pthread_setname_np (handle, name);
102135
103136 if (ret) {
104137 throw std::runtime_error (" Unable to set thread name, error code" + std::to_string (ret));
105138 }
139+
106140#endif
107141
108142 return Result::ok;
109143}
110144
111145Result set_name (std::jthread& thread, const char * name) {
112- #ifndef TARGET_OS_MAC
113146 const auto handle = thread.native_handle ();
114147 return set_name (handle, name);
115- #else
116- #pragma message WARN("Setting thread names is not implemented for this platform. Implement it, please!")
117- return Result::unsupported;
118- #endif
119148}
120149
121150Result set_name (std::thread& thread, const char * name) {
122- #ifndef TARGET_OS_MAC
123151 const auto handle = thread.native_handle ();
124152 return set_name (handle, name);
125- #else
126- #pragma message WARN("Setting thread names is not implemented for this platform. Implement it, please!")
127- return Result::unsupported;
128- #endif
129153}
130154
131155Result set_name (const char * name) {
132156#ifdef _WIN32
133157 auto handle = GetCurrentThread ();
134- return set_name (handle, name);
135- #elif defined __linux__ || defined __unix__ || defined TARGET_OS_MAC
136- auto handle = pthread_self ();
137- return set_name (handle, name);
138158#else
139- #pragma message WARN("Setting thread names is not implemented for this platform. Implement it, please!")
140- return Result::unsupported;
159+ auto handle = pthread_self ();
141160#endif
161+ return set_name (handle, name);
142162}
143163
144164std::expected<std::wstring, Result> get_name (auto & thread) {
@@ -191,14 +211,10 @@ std::expected<std::wstring, Result> get_name(std::thread& thread) {
191211std::expected<std::wstring, Result> get_name () {
192212#ifdef _WIN32
193213 auto handle = GetCurrentThread ();
194- return get_name (handle);
195- #elif defined __linux__ || defined __unix__ || TARGET_OS_MAC
196- auto handle = pthread_self ();
197- return get_name (handle);
198214#else
199- #pragma message WARN("Getting thread names is not implemented for this platform. Implement it, please!")
200- return std::unexpected (Result::unsupported);
215+ auto handle = pthread_self ();
201216#endif
217+ return get_name (handle);
202218}
203219
204220/*
@@ -228,5 +244,4 @@ unsigned int hardware_concurrency() {
228244 return hardware_concurrency (nullptr );
229245}
230246
231-
232247} // thread, ember
0 commit comments