diff --git a/libcxx/docs/Status/SpaceshipProjects.csv b/libcxx/docs/Status/SpaceshipProjects.csv --- a/libcxx/docs/Status/SpaceshipProjects.csv +++ b/libcxx/docs/Status/SpaceshipProjects.csv @@ -78,4 +78,4 @@ | `[fs.path.nonmember] `_,| `filesystem::path `_,None,Adrian Vogelsgesang,|In Progress| | `[fs.dir.entry.obs] `_,| `filesystem::directory_entry `_,None,Adrian Vogelsgesang,|In Progress| | `[re.submatch.op] `_,| sub_match,None,Mark de Wever,|In Progress| -| `[thread.thread.id] `_,| thread::id,None,Unassigned,|Not Started| +| `[thread.thread.id] `_,| `thread::id `_,None,Adrian Vogelsgesang,|Complete| diff --git a/libcxx/include/__threading_support b/libcxx/include/__threading_support --- a/libcxx/include/__threading_support +++ b/libcxx/include/__threading_support @@ -11,6 +11,7 @@ #define _LIBCPP___THREADING_SUPPORT #include <__availability> +#include <__compare/ordering.h> #include <__chrono/convert_to_timespec.h> #include <__chrono/duration.h> #include <__config> @@ -609,27 +610,34 @@ // on other platforms. We assume 0 works everywhere for now. __libcpp_thread_id __id_; + static _LIBCPP_INLINE_VISIBILITY + bool __eq_impl(__thread_id __x, __thread_id __y) _NOEXCEPT + { // don't pass id==0 to underlying routines + if (__x.__id_ == 0) return __y.__id_ == 0; + if (__y.__id_ == 0) return false; + return __libcpp_thread_id_equal(__x.__id_, __y.__id_); + } + static _LIBCPP_INLINE_VISIBILITY + 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) {} friend _LIBCPP_INLINE_VISIBILITY bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT - { // don't pass id==0 to underlying routines - if (__x.__id_ == 0) return __y.__id_ == 0; - if (__y.__id_ == 0) return false; - return __libcpp_thread_id_equal(__x.__id_, __y.__id_); - } + {return __eq_impl(__x, __y);} +#if _LIBCPP_STD_VER <= 17 friend _LIBCPP_INLINE_VISIBILITY bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT {return !(__x == __y);} friend _LIBCPP_INLINE_VISIBILITY 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 __lt_impl(__x, __y);} friend _LIBCPP_INLINE_VISIBILITY bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT {return !(__y < __x);} @@ -639,6 +647,15 @@ friend _LIBCPP_INLINE_VISIBILITY bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT {return !(__x < __y);} +#else // _LIBCPP_STD_VER <= 17 + friend _LIBCPP_INLINE_VISIBILITY + strong_ordering operator<=>(__thread_id __x, __thread_id __y) noexcept + { + if (__eq_impl(__x, __y)) return strong_ordering::equal; + if (__lt_impl(__x, __y)) return strong_ordering::less; + return strong_ordering::greater; + } +#endif // _LIBCPP_STD_VER <= 17 _LIBCPP_INLINE_VISIBILITY void __reset() { __id_ = 0; } diff --git a/libcxx/include/thread b/libcxx/include/thread --- a/libcxx/include/thread +++ b/libcxx/include/thread @@ -53,11 +53,12 @@ }; 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 basic_ostream& 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 --- /dev/null +++ b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/cmp.pass.cpp @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// + +// 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 +#include + +#include "test_macros.h" +#include "test_comparisons.h" + +int main(int, char**) { + AssertComparisonsAreNoexcept(); + AssertComparisonsReturnBool(); +#if TEST_STD_VER > 17 + AssertOrderAreNoexcept(); + AssertOrderReturn(); +#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 + + 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 --- a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/eq.pass.cpp +++ /dev/null @@ -1,35 +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 - -// - -// class thread::id - -// bool operator==(thread::id x, thread::id y); -// bool operator!=(thread::id x, thread::id y); - -#include -#include - -#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)); - - 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 --- a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/lt.pass.cpp +++ /dev/null @@ -1,46 +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 - -// - -// 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 -#include - -#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)); - } - - return 0; -}