[libcxx-commits] [libcxx] 41e7665 - [libc++] Implement `operator<=>` for `thread::id`
Adrian Vogelsgesang via libcxx-commits
libcxx-commits at lists.llvm.org
Sat Aug 13 17:31:12 PDT 2022
Author: Adrian Vogelsgesang
Date: 2022-08-13T17:30:55-07:00
New Revision: 41e7665c4b8ed47d1802b1dc8a41be3eacf805ad
URL: https://github.com/llvm/llvm-project/commit/41e7665c4b8ed47d1802b1dc8a41be3eacf805ad
DIFF: https://github.com/llvm/llvm-project/commit/41e7665c4b8ed47d1802b1dc8a41be3eacf805ad.diff
LOG: [libc++] Implement `operator<=>` for `thread::id`
The new operator<=> is mapped onto the existing functions
__libcpp_thread_id_equal and __libcpp_thread_id_less. Introducing a
new __libcpp_thread_id_compare_three_way might lead to more efficient
code. Given that we can still introduce __libcpp_thread_id_compare_three_way
later, for this commit I opted to not break ABI. If requested, I will
add __libcpp_thread_id_compare_three_way in a follow-up commit.
Implements part of P1614R2 "The Mothership has Landed"
Differential Revision: https://reviews.llvm.org/D131362
Added:
libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/cmp.pass.cpp
Modified:
libcxx/docs/Status/SpaceshipProjects.csv
libcxx/include/__threading_support
libcxx/include/thread
Removed:
libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/eq.pass.cpp
libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/lt.pass.cpp
################################################################################
diff --git a/libcxx/docs/Status/SpaceshipProjects.csv b/libcxx/docs/Status/SpaceshipProjects.csv
index 203ebac1b2818..5a8efbd9e21c8 100644
--- a/libcxx/docs/Status/SpaceshipProjects.csv
+++ b/libcxx/docs/Status/SpaceshipProjects.csv
@@ -78,4 +78,4 @@ Section,Description,Dependencies,Assignee,Complete
| `[fs.path.nonmember] <https://wg21.link/fs.path.nonmember>`_,| `filesystem::path <https://reviews.llvm.org/D130859>`_,None,Adrian Vogelsgesang,|In Progress|
| `[fs.dir.entry.obs] <https://wg21.link/fs.dir.entry.obs>`_,| `filesystem::directory_entry <https://reviews.llvm.org/D130860>`_,None,Adrian Vogelsgesang,|In Progress|
| `[re.submatch.op] <https://wg21.link/re.submatch.op>`_,| sub_match,None,Mark de Wever,|In Progress|
-| `[thread.thread.id] <https://wg21.link/thread.thread.id>`_,| `thread::id <https://reviews.llvm.org/D131362>`_,None,Adrian Vogelsgesang,|In Progress|
+| `[thread.thread.id] <https://wg21.link/thread.thread.id>`_,| `thread::id <https://reviews.llvm.org/D131362>`_,None,Adrian Vogelsgesang,|Complete|
diff --git a/libcxx/include/__threading_support b/libcxx/include/__threading_support
index c9119f3b2dffc..55f5af2f3f584 100644
--- a/libcxx/include/__threading_support
+++ b/libcxx/include/__threading_support
@@ -13,6 +13,7 @@
#include <__availability>
#include <__chrono/convert_to_timespec.h>
#include <__chrono/duration.h>
+#include <__compare/ordering.h>
#include <__config>
#include <__thread/poll_with_backoff.h>
#include <errno.h>
@@ -609,6 +610,14 @@ class _LIBCPP_TEMPLATE_VIS __thread_id
// on other platforms. We assume 0 works everywhere for now.
__libcpp_thread_id __id_;
+ static _LIBCPP_HIDE_FROM_ABI
+ bool __lt_impl(__thread_id __x, __thread_id __y) _NOEXCEPT
+ { // id==0 is always less than any other thread_id
+ if (__x.__id_ == 0) return __y.__id_ != 0;
+ if (__y.__id_ == 0) return false;
+ return __libcpp_thread_id_less(__x.__id_, __y.__id_);
+ }
+
public:
_LIBCPP_INLINE_VISIBILITY
__thread_id() _NOEXCEPT : __id_(0) {}
@@ -617,7 +626,11 @@ public:
void __reset() { __id_ = 0; }
friend _LIBCPP_HIDE_FROM_ABI bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT;
- friend _LIBCPP_HIDE_FROM_ABI bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT;
+#if _LIBCPP_STD_VER <= 17
+ friend _LIBCPP_HIDE_FROM_ABI bool operator<(__thread_id __x, __thread_id __y) _NOEXCEPT;
+#else // _LIBCPP_STD_VER <= 17
+ friend _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(__thread_id __x, __thread_id __y) noexcept;
+#endif // _LIBCPP_STD_VER <= 17
template<class _CharT, class _Traits>
friend
@@ -644,25 +657,35 @@ bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT {
return __libcpp_thread_id_equal(__x.__id_, __y.__id_);
}
+#if _LIBCPP_STD_VER <= 17
+
inline _LIBCPP_HIDE_FROM_ABI
bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT {
- return !(__x == __y);
+ return !(__x == __y);
}
inline _LIBCPP_HIDE_FROM_ABI
bool operator<(__thread_id __x, __thread_id __y) _NOEXCEPT {
- // id==0 is always less than any other thread_id
- if (__x.__id_ == 0)
- return __y.__id_ != 0;
- if (__y.__id_ == 0)
- return false;
- return __libcpp_thread_id_less(__x.__id_, __y.__id_);
+ return __thread_id::__lt_impl(__x.__id_, __y.__id_);
}
inline _LIBCPP_HIDE_FROM_ABI bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT { return !(__y < __x); }
inline _LIBCPP_HIDE_FROM_ABI bool operator>(__thread_id __x, __thread_id __y) _NOEXCEPT { return __y < __x; }
inline _LIBCPP_HIDE_FROM_ABI bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT { return !(__x < __y); }
+#else // _LIBCPP_STD_VER <= 17
+
+inline _LIBCPP_HIDE_FROM_ABI
+strong_ordering operator<=>(__thread_id __x, __thread_id __y) noexcept {
+ if (__x == __y)
+ return strong_ordering::equal;
+ if (__thread_id::__lt_impl(__x, __y))
+ return strong_ordering::less;
+ return strong_ordering::greater;
+}
+
+#endif // _LIBCPP_STD_VER <= 17
+
namespace this_thread
{
diff --git a/libcxx/include/thread b/libcxx/include/thread
index cde165039b3a2..8b8699271eeec 100644
--- a/libcxx/include/thread
+++ b/libcxx/include/thread
@@ -53,11 +53,12 @@ public:
};
bool operator==(thread::id x, thread::id y) noexcept;
-bool operator!=(thread::id x, thread::id y) noexcept;
-bool operator< (thread::id x, thread::id y) noexcept;
-bool operator<=(thread::id x, thread::id y) noexcept;
-bool operator> (thread::id x, thread::id y) noexcept;
-bool operator>=(thread::id x, thread::id y) noexcept;
+bool operator!=(thread::id x, thread::id y) noexcept; // removed in C++20
+bool operator< (thread::id x, thread::id y) noexcept; // removed in C++20
+bool operator<=(thread::id x, thread::id y) noexcept; // removed in C++20
+bool operator> (thread::id x, thread::id y) noexcept; // removed in C++20
+bool operator>=(thread::id x, thread::id y) noexcept; // removed in C++20
+strong_ordering operator<=>(thread::id x, thread::id y) noexcept; // C++20
template<class charT, class traits>
basic_ostream<charT, traits>&
diff --git a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/cmp.pass.cpp b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/cmp.pass.cpp
new file mode 100644
index 0000000000000..7be937aa948c5
--- /dev/null
+++ b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/cmp.pass.cpp
@@ -0,0 +1,69 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// UNSUPPORTED: no-threads
+
+// <thread>
+
+// class thread::id
+
+// bool operator==(thread::id x, thread::id y) noexcept;
+// bool operator!=(thread::id x, thread::id y) noexcept;
+// bool operator< (thread::id x, thread::id y) noexcept;
+// bool operator<=(thread::id x, thread::id y) noexcept;
+// bool operator> (thread::id x, thread::id y) noexcept;
+// bool operator>=(thread::id x, thread::id y) noexcept;
+// strong_ordering operator<=>(thread::id x, thread::id y) noexcept;
+
+#include <thread>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_comparisons.h"
+
+int main(int, char**) {
+ AssertComparisonsAreNoexcept<std::thread::id>();
+ AssertComparisonsReturnBool<std::thread::id>();
+#if TEST_STD_VER > 17
+ AssertOrderAreNoexcept<std::thread::id>();
+ AssertOrderReturn<std::strong_ordering, std::thread::id>();
+#endif
+
+ std::thread::id id1;
+ std::thread::id id2;
+ std::thread::id id3 = std::this_thread::get_id();
+
+ // `id1` and `id2` should compare equal
+ assert(testComparisons(id1, id2, /*isEqual*/ true, /*isLess*/ false));
+#if TEST_STD_VER > 17
+ assert(testOrder(id1, id2, std::strong_ordering::equal));
+#endif
+
+ // Test `t1` and `t3` which are not equal
+ bool isLess = id1 < id3;
+ assert(testComparisons(id1, id3, /*isEqual*/ false, isLess));
+#if TEST_STD_VER > 17
+ assert(testOrder(id1, id3, isLess ? std::strong_ordering::less : std::strong_ordering::greater));
+#endif
+
+ // Regression tests for https://github.com/llvm/llvm-project/issues/56187
+ // libc++ previously declared the comparison operators as hidden friends
+ // which was non-conforming.
+ assert(std::operator==(id1, id2));
+#if TEST_STD_VER <= 17
+ assert(!std::operator!=(id1, id2));
+ assert(!std::operator<(id1, id2));
+ assert(std::operator<=(id1, id2));
+ assert(!std::operator>(id1, id2));
+ assert(std::operator>=(id1, id2));
+#else
+ assert(std::operator<=>(id1, id2) == std::strong_ordering::equal);
+#endif
+
+ return 0;
+}
diff --git a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/eq.pass.cpp b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/eq.pass.cpp
deleted file mode 100644
index 01d505c325cc7..0000000000000
--- a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/eq.pass.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-//
-// UNSUPPORTED: no-threads
-
-// <thread>
-
-// class thread::id
-
-// bool operator==(thread::id x, thread::id y);
-// bool operator!=(thread::id x, thread::id y);
-
-#include <thread>
-#include <cassert>
-
-#include "test_macros.h"
-
-int main(int, char**)
-{
- std::thread::id id0;
- std::thread::id id1;
- id1 = id0;
- assert( (id1 == id0));
- assert(!(id1 != id0));
- id1 = std::this_thread::get_id();
- assert(!(id1 == id0));
- assert( (id1 != id0));
-
- // Regression tests for https://github.com/llvm/llvm-project/issues/56187
- // libc++ previously declared the comparison operators as hidden friends
- // which was non-conforming.
- assert(!std::operator==(id1, id0));
- assert(std::operator!=(id1, id0));
-
- return 0;
-}
diff --git a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/lt.pass.cpp b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/lt.pass.cpp
deleted file mode 100644
index 7519f04ebb353..0000000000000
--- a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/lt.pass.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-//
-// UNSUPPORTED: no-threads
-
-// <thread>
-
-// class thread::id
-
-// bool operator< (thread::id x, thread::id y);
-// bool operator<=(thread::id x, thread::id y);
-// bool operator> (thread::id x, thread::id y);
-// bool operator>=(thread::id x, thread::id y);
-
-#include <thread>
-#include <cassert>
-
-#include "test_macros.h"
-
-int main(int, char**)
-{
- std::thread::id id0;
- std::thread::id id1;
- std::thread::id id2 = std::this_thread::get_id();
- assert(!(id0 < id1));
- assert( (id0 <= id1));
- assert(!(id0 > id1));
- assert( (id0 >= id1));
- assert(!(id0 == id2));
- if (id0 < id2) {
- assert( (id0 <= id2));
- assert(!(id0 > id2));
- assert(!(id0 >= id2));
- } else {
- assert(!(id0 <= id2));
- assert( (id0 > id2));
- assert( (id0 >= id2));
- }
-
- // Regression tests for https://github.com/llvm/llvm-project/issues/56187
- // libc++ previously declared the comparison operators as hidden friends
- // which was non-conforming.
- assert(!std::operator<(id0, id1));
- assert(std::operator<=(id0, id1));
- assert(!std::operator>(id0, id1));
- assert(std::operator>=(id0, id1));
-
- return 0;
-}
More information about the libcxx-commits
mailing list