[libcxx-commits] [libcxx] [libc++] Introduce a free function __thread_hardware_concurrency() (PR #232284)
Michael G. Kazakov via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Oct 15 04:33:28 PDT 2026
https://github.com/mikekazakov created https://github.com/llvm/llvm-project/pull/232284
It allows to query the available hardware concurrency without depending on entirety of `std::thread`.
Required for #229804.
>From ed1b1aca39f64b3b1d237889a4cb402361940358 Mon Sep 17 00:00:00 2001
From: Michael Kazakov <mike.kazakov at gmail.com>
Date: Thu, 15 Oct 2026 12:30:56 +0100
Subject: [PATCH] Introduce a free function __thread_hardware_concurrency()
---
libcxx/include/CMakeLists.txt | 1 +
libcxx/include/__configuration/availability.h | 6 +++
.../include/__thread/hardware_concurrency.h | 37 ++++++++++++++
libcxx/include/__thread/thread.h | 9 +++-
libcxx/include/module.modulemap.in | 1 +
libcxx/src/thread.cpp | 49 ++++++++++---------
6 files changed, 79 insertions(+), 24 deletions(-)
create mode 100644 libcxx/include/__thread/hardware_concurrency.h
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 9af3d00f36f7e6..0de8b813a1dfb7 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -828,6 +828,7 @@ set(files
__system_error/system_error.h
__system_error/throw_system_error.h
__thread/formatter.h
+ __thread/hardware_concurrency.h
__thread/id.h
__thread/jthread.h
__thread/poll_with_backoff.h
diff --git a/libcxx/include/__configuration/availability.h b/libcxx/include/__configuration/availability.h
index 75d911438e4af1..805a9edab14bbf 100644
--- a/libcxx/include/__configuration/availability.h
+++ b/libcxx/include/__configuration/availability.h
@@ -260,6 +260,12 @@
#endif
+// This controls the availability of the free function std::__thread_hardware_concurrency().
+// It has the same semantics as std::[j]thread::hardware_concurrency(), but allows to query this information
+// without depending on std::thread itself.
+#define _LIBCPP_AVAILABILITY_HAS_HARDWARE_CONCURRENCY_FREE_FUNCTION _LIBCPP_INTRODUCED_IN_LLVM_24
+#define _LIBCPP_AVAILABILITY_HARDWARE_CONCURRENCY_FREE_FUNCTION _LIBCPP_INTRODUCED_IN_LLVM_24_ATTRIBUTE
+
// This controls the availability of the C++26 debugging functions.
// The platform specific implementation is built in the library.
#define _LIBCPP_AVAILABILITY_HAS_DEBUGGING _LIBCPP_INTRODUCED_IN_LLVM_24
diff --git a/libcxx/include/__thread/hardware_concurrency.h b/libcxx/include/__thread/hardware_concurrency.h
new file mode 100644
index 00000000000000..c5ee41686a939c
--- /dev/null
+++ b/libcxx/include/__thread/hardware_concurrency.h
@@ -0,0 +1,37 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___THREAD_HARDWARE_CONCURRENCY_H
+#define _LIBCPP___THREAD_HARDWARE_CONCURRENCY_H
+
+#include <__config>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+_LIBCPP_BEGIN_EXPLICIT_ABI_ANNOTATIONS
+
+#if _LIBCPP_HAS_THREADS
+
+[[__nodiscard__]] _LIBCPP_AVAILABILITY_HARDWARE_CONCURRENCY_FREE_FUNCTION
+ _LIBCPP_EXPORTED_FROM_ABI unsigned __thread_hardware_concurrency() _NOEXCEPT;
+
+#endif // _LIBCPP_HAS_THREADS
+
+_LIBCPP_END_EXPLICIT_ABI_ANNOTATIONS
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___THREAD_HARDWARE_CONCURRENCY_H
diff --git a/libcxx/include/__thread/thread.h b/libcxx/include/__thread/thread.h
index 4fd51c12a6dc2b..314fa2d48f6cee 100644
--- a/libcxx/include/__thread/thread.h
+++ b/libcxx/include/__thread/thread.h
@@ -22,6 +22,7 @@
#include <__memory/unique_ptr.h>
#include <__mutex/mutex.h>
#include <__system_error/throw_system_error.h>
+#include <__thread/hardware_concurrency.h>
#include <__thread/id.h>
#include <__thread/support.h>
#include <__type_traits/decay.h>
@@ -262,7 +263,13 @@ class _LIBCPP_EXPORTED_FROM_ABI thread {
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI id get_id() const _NOEXCEPT { return __libcpp_thread_get_id(&__t_); }
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() _NOEXCEPT { return __t_; }
- [[__nodiscard__]] static unsigned hardware_concurrency() _NOEXCEPT;
+# if defined(_LIBCPP_BUILDING_LIBRARY) || !_LIBCPP_AVAILABILITY_HAS_HARDWARE_CONCURRENCY_FREE_FUNCTION
+ [[__nodiscard__]] _LIBCPP_EXPORTED_FROM_ABI static unsigned hardware_concurrency() _NOEXCEPT;
+# else
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static unsigned hardware_concurrency() _NOEXCEPT {
+ return std::__thread_hardware_concurrency();
+ }
+# endif
};
inline _LIBCPP_HIDE_FROM_ABI void swap(thread& __x, thread& __y) _NOEXCEPT { __x.swap(__y); }
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 2f6640f8469a5b..460299aea1ed04 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -2202,6 +2202,7 @@ module std {
module thread {
module formatter { header "__thread/formatter.h" }
+ module hardware_concurrency { header "__thread/hardware_concurrency.h" }
module id { header "__thread/id.h" }
module jthread { header "__thread/jthread.h" }
module poll_with_backoff { header "__thread/poll_with_backoff.h" }
diff --git a/libcxx/src/thread.cpp b/libcxx/src/thread.cpp
index 7b0890858e9d64..e931c9288710d1 100644
--- a/libcxx/src/thread.cpp
+++ b/libcxx/src/thread.cpp
@@ -64,29 +64,8 @@ void thread::detach() {
std::__throw_system_error(ec, "thread::detach failed");
}
-unsigned thread::hardware_concurrency() noexcept {
-#if defined(_SC_NPROCESSORS_ONLN)
- long result = sysconf(_SC_NPROCESSORS_ONLN);
- // sysconf returns -1 if the name is invalid, the option does not exist or
- // does not have a definite limit.
- // if sysconf returns some other negative number, we have no idea
- // what is going on. Default to something safe.
- if (result < 0)
- return 0;
- return static_cast<unsigned>(result);
-#elif defined(_WIN32)
- return static_cast<unsigned>(GetActiveProcessorCount(ALL_PROCESSOR_GROUPS));
-#else // defined(CTL_HW) && defined(HW_NCPU)
- // TODO: grovel through /proc or check cpuid on x86 and similar
- // instructions on other architectures.
-# if defined(_LIBCPP_WARNING)
- _LIBCPP_WARNING("hardware_concurrency not yet implemented")
-# else
-# warning hardware_concurrency not yet implemented
-# endif
- return 0; // Means not computable [thread.thread.static]
-#endif // defined(CTL_HW) && defined(HW_NCPU)
-}
+// Defined here only for backwards compatibility
+unsigned thread::hardware_concurrency() noexcept { return __thread_hardware_concurrency(); }
namespace this_thread {
@@ -171,5 +150,29 @@ void __thread_struct::notify_all_at_thread_exit(condition_variable* cv, mutex* m
void __thread_struct::__make_ready_at_thread_exit(__assoc_sub_state* __s) { __p_->__make_ready_at_thread_exit(__s); }
+unsigned __thread_hardware_concurrency() noexcept {
+#if defined(_SC_NPROCESSORS_ONLN)
+ long result = sysconf(_SC_NPROCESSORS_ONLN);
+ // sysconf returns -1 if the name is invalid, the option does not exist or
+ // does not have a definite limit.
+ // if sysconf returns some other negative number, we have no idea
+ // what is going on. Default to something safe.
+ if (result < 0)
+ return 0;
+ return static_cast<unsigned>(result);
+#elif defined(_WIN32)
+ return static_cast<unsigned>(GetActiveProcessorCount(ALL_PROCESSOR_GROUPS));
+#else // defined(CTL_HW) && defined(HW_NCPU)
+ // TODO: grovel through /proc or check cpuid on x86 and similar
+ // instructions on other architectures.
+# if defined(_LIBCPP_WARNING)
+ _LIBCPP_WARNING("hardware_concurrency not yet implemented")
+# else
+# warning hardware_concurrency not yet implemented
+# endif
+ return 0; // Means not computable [thread.thread.static]
+#endif // defined(CTL_HW) && defined(HW_NCPU)
+}
+
_LIBCPP_END_EXPLICIT_ABI_ANNOTATIONS
_LIBCPP_END_NAMESPACE_STD
More information about the libcxx-commits
mailing list