From 62cfa3a0b5d20e6d0d5abe95412ab271d934083c Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Wed, 3 Jun 2020 11:51:59 -0400 Subject: [PATCH] [libc++] Support move construction and assignment in in C++03 Libc++ provides support for in C++03 as an extension. Furthermore, it does not support any compiler that doesn't have rvalue references. It is hence possible to provide the move constructor and move assignment operator in C++03. --- libcxx/include/thread | 26 +++++++--------- .../thread.thread.assign/move.pass.cpp | 26 +++++++++------- .../thread.thread.assign/move2.pass.cpp | 35 +++++----------------- .../thread.thread.constr/move.pass.cpp | 25 +++++++--------- 4 files changed, 44 insertions(+), 68 deletions(-) diff --git a/libcxx/include/thread b/libcxx/include/thread index 3b55342..22aa4f2 100644 --- a/libcxx/include/thread +++ b/libcxx/include/thread @@ -241,12 +241,19 @@ public: #endif ~thread(); -#ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY - thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) {__t.__t_ = _LIBCPP_NULL_THREAD;} + thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) { + __t.__t_ = _LIBCPP_NULL_THREAD; + } + _LIBCPP_INLINE_VISIBILITY - thread& operator=(thread&& __t) _NOEXCEPT; -#endif // _LIBCPP_CXX03_LANG + thread& operator=(thread&& __t) _NOEXCEPT { + if (!__libcpp_thread_isnull(&__t_)) + terminate(); + __t_ = __t.__t_; + __t.__t_ = _LIBCPP_NULL_THREAD; + return *this; + } _LIBCPP_INLINE_VISIBILITY void swap(thread& __t) _NOEXCEPT {_VSTD::swap(__t_, __t.__t_);} @@ -304,17 +311,6 @@ thread::thread(_Fp&& __f, _Args&&... __args) __throw_system_error(__ec, "thread constructor failed"); } -inline -thread& -thread::operator=(thread&& __t) _NOEXCEPT -{ - if (!__libcpp_thread_isnull(&__t_)) - terminate(); - __t_ = __t.__t_; - __t.__t_ = _LIBCPP_NULL_THREAD; - return *this; -} - #else // _LIBCPP_CXX03_LANG template diff --git a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.assign/move.pass.cpp b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.assign/move.pass.cpp index 54229a4..c210475 100644 --- a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.assign/move.pass.cpp +++ b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.assign/move.pass.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// // -// UNSUPPORTED: libcpp-has-no-threads, c++03 +// UNSUPPORTED: libcpp-has-no-threads // @@ -16,6 +16,7 @@ #include #include +#include #include "test_macros.h" @@ -30,12 +31,10 @@ public: G(const G& g) : alive_(g.alive_) {++n_alive;} ~G() {alive_ = 0; --n_alive;} - void operator()(int i, double j) + void operator()() { assert(alive_ == 1); assert(n_alive >= 1); - assert(i == 5); - assert(j == 5.5); op_run = true; } }; @@ -45,22 +44,27 @@ bool G::op_run = false; int main(int, char**) { + assert(G::n_alive == 0); + assert(!G::op_run); { - assert(G::n_alive == 0); - assert(!G::op_run); - { G g; - std::thread t0(g, 5, 5.5); + assert(G::n_alive == 1); + assert(!G::op_run); + + std::thread t0(g); std::thread::id id = t0.get_id(); + std::thread t1; t1 = std::move(t0); assert(t1.get_id() == id); assert(t0.get_id() == std::thread::id()); + t1.join(); - } - assert(G::n_alive == 0); + assert(G::n_alive == 1); assert(G::op_run); } + assert(G::n_alive == 0); + assert(G::op_run); - return 0; + return 0; } diff --git a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.assign/move2.pass.cpp b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.assign/move2.pass.cpp index f836696..27cbf3a 100644 --- a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.assign/move2.pass.cpp +++ b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.assign/move2.pass.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// // // UNSUPPORTED: libcpp-has-no-threads -// UNSUPPORTED: c++03 // @@ -16,38 +15,18 @@ // thread& operator=(thread&& t); #include -#include -#include #include +#include +#include +#include #include "test_macros.h" -class G +struct G { - int alive_; -public: - static int n_alive; - static bool op_run; - - G() : alive_(1) {++n_alive;} - G(const G& g) : alive_(g.alive_) {++n_alive;} - ~G() {alive_ = 0; --n_alive;} - - - - void operator()(int i, double j) - { - assert(alive_ == 1); - assert(n_alive >= 1); - assert(i == 5); - assert(j == 5.5); - op_run = true; - } + void operator()() { } }; -int G::n_alive = 0; -bool G::op_run = false; - void f1() { std::_Exit(0); @@ -58,11 +37,11 @@ int main(int, char**) std::set_terminate(f1); { G g; - std::thread t0(g, 5, 5.5); + std::thread t0(g); std::thread t1; t0 = std::move(t1); assert(false); } - return 0; + return 0; } diff --git a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/move.pass.cpp b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/move.pass.cpp index d171c96..55265cc 100644 --- a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/move.pass.cpp +++ b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/move.pass.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// // -// UNSUPPORTED: libcpp-has-no-threads, c++03 +// UNSUPPORTED: libcpp-has-no-threads // @@ -15,9 +15,9 @@ // thread(thread&& t); #include -#include -#include #include +#include +#include #include "test_macros.h" @@ -38,15 +38,6 @@ public: assert(n_alive >= 1); op_run = true; } - - void operator()(int i, double j) - { - assert(alive_ == 1); - assert(n_alive >= 1); - assert(i == 5); - assert(j == 5.5); - op_run = true; - } }; int G::n_alive = 0; @@ -54,20 +45,26 @@ bool G::op_run = false; int main(int, char**) { + assert(G::n_alive == 0); + assert(!G::op_run); { G g; assert(G::n_alive == 1); assert(!G::op_run); - std::thread t0(g, 5, 5.5); + + std::thread t0(g); std::thread::id id = t0.get_id(); + std::thread t1 = std::move(t0); assert(t1.get_id() == id); assert(t0.get_id() == std::thread::id()); + t1.join(); assert(G::n_alive == 1); assert(G::op_run); } assert(G::n_alive == 0); + assert(G::op_run); - return 0; + return 0; } -- 2.7.4