diff options
author | Howard Hinnant <hhinnant@apple.com> | 2010-08-28 21:01:06 +0000 |
---|---|---|
committer | Howard Hinnant <hhinnant@apple.com> | 2010-08-28 21:01:06 +0000 |
commit | 8759d9d4d018351172b30dd41bdcbbe40af86ed8 (patch) | |
tree | 51b40ea60171bc659a2dbcc8f1af79f3acbe5089 /libcxx/test | |
parent | 7a05e6dca2c87f9b5294acec50ac59db9a97acb7 (diff) | |
download | bcm5719-llvm-8759d9d4d018351172b30dd41bdcbbe40af86ed8.tar.gz bcm5719-llvm-8759d9d4d018351172b30dd41bdcbbe40af86ed8.zip |
[futures.promise]. Depends on rvalue-ref support to work 100%.
llvm-svn: 112388
Diffstat (limited to 'libcxx/test')
20 files changed, 1220 insertions, 0 deletions
diff --git a/libcxx/test/thread/futures/futures.promise/alloc_ctor.pass.cpp b/libcxx/test/thread/futures/futures.promise/alloc_ctor.pass.cpp new file mode 100644 index 00000000000..da7353cf65c --- /dev/null +++ b/libcxx/test/thread/futures/futures.promise/alloc_ctor.pass.cpp @@ -0,0 +1,49 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <future> + +// class promise<R> + +// template <class Allocator> +// promise(allocator_arg_t, const Allocator& a); + +#include <future> +#include <cassert> + +#include "../test_allocator.h" + +int main() +{ + assert(test_alloc_base::count == 0); + { + std::promise<int> p(std::allocator_arg, test_allocator<int>()); + assert(test_alloc_base::count == 1); + std::future<int> f = p.get_future(); + assert(test_alloc_base::count == 1); + assert(f.valid()); + } + assert(test_alloc_base::count == 0); + { + std::promise<int&> p(std::allocator_arg, test_allocator<int>()); + assert(test_alloc_base::count == 1); + std::future<int&> f = p.get_future(); + assert(test_alloc_base::count == 1); + assert(f.valid()); + } + assert(test_alloc_base::count == 0); + { + std::promise<void> p(std::allocator_arg, test_allocator<void>()); + assert(test_alloc_base::count == 1); + std::future<void> f = p.get_future(); + assert(test_alloc_base::count == 1); + assert(f.valid()); + } + assert(test_alloc_base::count == 0); +} diff --git a/libcxx/test/thread/futures/futures.promise/copy_assign.fail.cpp b/libcxx/test/thread/futures/futures.promise/copy_assign.fail.cpp new file mode 100644 index 00000000000..04aefe80b4f --- /dev/null +++ b/libcxx/test/thread/futures/futures.promise/copy_assign.fail.cpp @@ -0,0 +1,87 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <future> + +// class promise<R> + +// promise& operator=(const promise& rhs) = delete; + +#include <future> +#include <cassert> + +#include "../test_allocator.h" + +int main() +{ + assert(test_alloc_base::count == 0); + { + std::promise<int> p0(std::allocator_arg, test_allocator<int>()); + std::promise<int> p(std::allocator_arg, test_allocator<int>()); + assert(test_alloc_base::count == 2); + p = p0; + assert(test_alloc_base::count == 1); + std::future<int> f = p.get_future(); + assert(test_alloc_base::count == 1); + assert(f.valid()); + try + { + f = p0.get_future(); + assert(false); + } + catch (const std::future_error& e) + { + assert(e.code() == make_error_code(std::future_errc::no_state)); + } + assert(test_alloc_base::count == 1); + } + assert(test_alloc_base::count == 0); + { + std::promise<int&> p0(std::allocator_arg, test_allocator<int>()); + std::promise<int&> p(std::allocator_arg, test_allocator<int>()); + assert(test_alloc_base::count == 2); + p = p0; + assert(test_alloc_base::count == 1); + std::future<int&> f = p.get_future(); + assert(test_alloc_base::count == 1); + assert(f.valid()); + try + { + f = p0.get_future(); + assert(false); + } + catch (const std::future_error& e) + { + assert(e.code() == make_error_code(std::future_errc::no_state)); + } + assert(test_alloc_base::count == 1); + } + assert(test_alloc_base::count == 0); + { + std::promise<void> p0(std::allocator_arg, test_allocator<void>()); + std::promise<void> p(std::allocator_arg, test_allocator<void>()); + assert(test_alloc_base::count == 2); + p = p0; + assert(test_alloc_base::count == 1); + std::future<void> f = p.get_future(); + assert(test_alloc_base::count == 1); + assert(f.valid()); + try + { + f = p0.get_future(); + assert(false); + } + catch (const std::future_error& e) + { + assert(e.code() == make_error_code(std::future_errc::no_state)); + } + assert(test_alloc_base::count == 1); + } + assert(test_alloc_base::count == 0); +} diff --git a/libcxx/test/thread/futures/futures.promise/copy_ctor.fail.cpp b/libcxx/test/thread/futures/futures.promise/copy_ctor.fail.cpp new file mode 100644 index 00000000000..d295ad3b7d9 --- /dev/null +++ b/libcxx/test/thread/futures/futures.promise/copy_ctor.fail.cpp @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <future> + +// class promise<R> + +// promise(const promise&) = delete; + +#include <future> +#include <cassert> + +#include "../test_allocator.h" + +int main() +{ + assert(test_alloc_base::count == 0); + { + std::promise<int> p0(std::allocator_arg, test_allocator<int>()); + std::promise<int> p(p0); + assert(test_alloc_base::count == 1); + std::future<int> f = p.get_future(); + assert(test_alloc_base::count == 1); + assert(f.valid()); + try + { + f = p0.get_future(); + assert(false); + } + catch (const std::future_error& e) + { + assert(e.code() == make_error_code(std::future_errc::no_state)); + } + assert(test_alloc_base::count == 1); + } + assert(test_alloc_base::count == 0); + { + std::promise<int&> p0(std::allocator_arg, test_allocator<int>()); + std::promise<int&> p(p0); + assert(test_alloc_base::count == 1); + std::future<int&> f = p.get_future(); + assert(test_alloc_base::count == 1); + assert(f.valid()); + try + { + f = p0.get_future(); + assert(false); + } + catch (const std::future_error& e) + { + assert(e.code() == make_error_code(std::future_errc::no_state)); + } + assert(test_alloc_base::count == 1); + } + assert(test_alloc_base::count == 0); + { + std::promise<void> p0(std::allocator_arg, test_allocator<void>()); + std::promise<void> p(p0); + assert(test_alloc_base::count == 1); + std::future<void> f = p.get_future(); + assert(test_alloc_base::count == 1); + assert(f.valid()); + try + { + f = p0.get_future(); + assert(false); + } + catch (const std::future_error& e) + { + assert(e.code() == make_error_code(std::future_errc::no_state)); + } + assert(test_alloc_base::count == 1); + } + assert(test_alloc_base::count == 0); +} diff --git a/libcxx/test/thread/futures/futures.promise/default.pass.cpp b/libcxx/test/thread/futures/futures.promise/default.pass.cpp new file mode 100644 index 00000000000..53b0dd12a93 --- /dev/null +++ b/libcxx/test/thread/futures/futures.promise/default.pass.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <future> + +// class promise<R> + +// promise(); + +#include <future> +#include <cassert> + +int main() +{ + { + std::promise<int> p; + std::future<int> f = p.get_future(); + assert(f.valid()); + } + { + std::promise<int&> p; + std::future<int&> f = p.get_future(); + assert(f.valid()); + } + { + std::promise<void> p; + std::future<void> f = p.get_future(); + assert(f.valid()); + } +} diff --git a/libcxx/test/thread/futures/futures.promise/dtor.pass.cpp b/libcxx/test/thread/futures/futures.promise/dtor.pass.cpp new file mode 100644 index 00000000000..95601eb32b7 --- /dev/null +++ b/libcxx/test/thread/futures/futures.promise/dtor.pass.cpp @@ -0,0 +1,106 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <future> + +// class promise<R> + +// ~promise(); + +#include <future> +#include <cassert> + +int main() +{ + { + typedef int T; + std::future<T> f; + { + std::promise<T> p; + f = p.get_future(); + p.set_value(3); + } + assert(f.get() == 3); + } + { + typedef int T; + std::future<T> f; + { + std::promise<T> p; + f = p.get_future(); + } + try + { + T i = f.get(); + assert(false); + } + catch (const std::future_error& e) + { + assert(e.code() == make_error_code(std::future_errc::broken_promise)); + } + } + + { + typedef int& T; + int i = 4; + std::future<T> f; + { + std::promise<T> p; + f = p.get_future(); + p.set_value(i); + } + assert(&f.get() == &i); + } + { + typedef int& T; + std::future<T> f; + { + std::promise<T> p; + f = p.get_future(); + } + try + { + T i = f.get(); + assert(false); + } + catch (const std::future_error& e) + { + assert(e.code() == make_error_code(std::future_errc::broken_promise)); + } + } + + { + typedef void T; + std::future<T> f; + { + std::promise<T> p; + f = p.get_future(); + p.set_value(); + } + f.get(); + assert(true); + } + { + typedef void T; + std::future<T> f; + { + std::promise<T> p; + f = p.get_future(); + } + try + { + f.get(); + assert(false); + } + catch (const std::future_error& e) + { + assert(e.code() == make_error_code(std::future_errc::broken_promise)); + } + } +} diff --git a/libcxx/test/thread/futures/futures.promise/move_assign.pass.cpp b/libcxx/test/thread/futures/futures.promise/move_assign.pass.cpp new file mode 100644 index 00000000000..4d2283f9059 --- /dev/null +++ b/libcxx/test/thread/futures/futures.promise/move_assign.pass.cpp @@ -0,0 +1,89 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <future> + +// class promise<R> + +// promise& operator=(promise&& rhs); + +#include <future> +#include <cassert> + +#include "../test_allocator.h" + +int main() +{ +#ifdef _LIBCPP_MOVE + assert(test_alloc_base::count == 0); + { + std::promise<int> p0(std::allocator_arg, test_allocator<int>()); + std::promise<int> p(std::allocator_arg, test_allocator<int>()); + assert(test_alloc_base::count == 2); + p = std::move(p0); + assert(test_alloc_base::count == 1); + std::future<int> f = p.get_future(); + assert(test_alloc_base::count == 1); + assert(f.valid()); + try + { + f = p0.get_future(); + assert(false); + } + catch (const std::future_error& e) + { + assert(e.code() == make_error_code(std::future_errc::no_state)); + } + assert(test_alloc_base::count == 1); + } + assert(test_alloc_base::count == 0); + { + std::promise<int&> p0(std::allocator_arg, test_allocator<int>()); + std::promise<int&> p(std::allocator_arg, test_allocator<int>()); + assert(test_alloc_base::count == 2); + p = std::move(p0); + assert(test_alloc_base::count == 1); + std::future<int&> f = p.get_future(); + assert(test_alloc_base::count == 1); + assert(f.valid()); + try + { + f = p0.get_future(); + assert(false); + } + catch (const std::future_error& e) + { + assert(e.code() == make_error_code(std::future_errc::no_state)); + } + assert(test_alloc_base::count == 1); + } + assert(test_alloc_base::count == 0); + { + std::promise<void> p0(std::allocator_arg, test_allocator<void>()); + std::promise<void> p(std::allocator_arg, test_allocator<void>()); + assert(test_alloc_base::count == 2); + p = std::move(p0); + assert(test_alloc_base::count == 1); + std::future<void> f = p.get_future(); + assert(test_alloc_base::count == 1); + assert(f.valid()); + try + { + f = p0.get_future(); + assert(false); + } + catch (const std::future_error& e) + { + assert(e.code() == make_error_code(std::future_errc::no_state)); + } + assert(test_alloc_base::count == 1); + } + assert(test_alloc_base::count == 0); +#endif // _LIBCPP_MOVE +} diff --git a/libcxx/test/thread/futures/futures.promise/move_ctor.pass.cpp b/libcxx/test/thread/futures/futures.promise/move_ctor.pass.cpp new file mode 100644 index 00000000000..caaaeebbf7c --- /dev/null +++ b/libcxx/test/thread/futures/futures.promise/move_ctor.pass.cpp @@ -0,0 +1,83 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <future> + +// class promise<R> + +// promise(promise&& rhs); + +#include <future> +#include <cassert> + +#include "../test_allocator.h" + +int main() +{ +#ifdef _LIBCPP_MOVE + assert(test_alloc_base::count == 0); + { + std::promise<int> p0(std::allocator_arg, test_allocator<int>()); + std::promise<int> p(std::move(p0)); + assert(test_alloc_base::count == 1); + std::future<int> f = p.get_future(); + assert(test_alloc_base::count == 1); + assert(f.valid()); + try + { + f = p0.get_future(); + assert(false); + } + catch (const std::future_error& e) + { + assert(e.code() == make_error_code(std::future_errc::no_state)); + } + assert(test_alloc_base::count == 1); + } + assert(test_alloc_base::count == 0); + { + std::promise<int&> p0(std::allocator_arg, test_allocator<int>()); + std::promise<int&> p(std::move(p0)); + assert(test_alloc_base::count == 1); + std::future<int&> f = p.get_future(); + assert(test_alloc_base::count == 1); + assert(f.valid()); + try + { + f = p0.get_future(); + assert(false); + } + catch (const std::future_error& e) + { + assert(e.code() == make_error_code(std::future_errc::no_state)); + } + assert(test_alloc_base::count == 1); + } + assert(test_alloc_base::count == 0); + { + std::promise<void> p0(std::allocator_arg, test_allocator<void>()); + std::promise<void> p(std::move(p0)); + assert(test_alloc_base::count == 1); + std::future<void> f = p.get_future(); + assert(test_alloc_base::count == 1); + assert(f.valid()); + try + { + f = p0.get_future(); + assert(false); + } + catch (const std::future_error& e) + { + assert(e.code() == make_error_code(std::future_errc::no_state)); + } + assert(test_alloc_base::count == 1); + } + assert(test_alloc_base::count == 0); +#endif // _LIBCPP_MOVE +} diff --git a/libcxx/test/thread/futures/futures.promise/set_exception.pass.cpp b/libcxx/test/thread/futures/futures.promise/set_exception.pass.cpp new file mode 100644 index 00000000000..97c4351dd64 --- /dev/null +++ b/libcxx/test/thread/futures/futures.promise/set_exception.pass.cpp @@ -0,0 +1,45 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <future> + +// class promise<R> + +// void set_exception(exception_ptr p); + +#include <future> +#include <cassert> + +int main() +{ + { + typedef int T; + std::promise<T> p; + std::future<T> f = p.get_future(); + p.set_exception(std::make_exception_ptr(3)); + try + { + f.get(); + assert(false); + } + catch (int i) + { + assert(i == 3); + } + try + { + p.set_exception(std::make_exception_ptr(3)); + assert(false); + } + catch (const std::future_error& e) + { + assert(e.code() == make_error_code(std::future_errc::promise_already_satisfied)); + } + } +} diff --git a/libcxx/test/thread/futures/futures.promise/set_exception_at_thread_exit.pass.cpp b/libcxx/test/thread/futures/futures.promise/set_exception_at_thread_exit.pass.cpp new file mode 100644 index 00000000000..ce1f758dd3a --- /dev/null +++ b/libcxx/test/thread/futures/futures.promise/set_exception_at_thread_exit.pass.cpp @@ -0,0 +1,42 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <future> + +// class promise<R> + +// void promise::set_exception_at_thread_exit(exception_ptr p); + +#include <future> +#include <cassert> + +void func(std::promise<int>& p) +{ + const int i = 5; + p.set_exception_at_thread_exit(std::make_exception_ptr(3)); +} + +int main() +{ + { + typedef int T; + std::promise<T> p; + std::future<T> f = p.get_future(); + std::thread(func, std::move(p)).detach(); + try + { + f.get(); + assert(false); + } + catch (int i) + { + assert(i == 3); + } + } +} diff --git a/libcxx/test/thread/futures/futures.promise/set_lvalue.pass.cpp b/libcxx/test/thread/futures/futures.promise/set_lvalue.pass.cpp new file mode 100644 index 00000000000..4ebd8dd25df --- /dev/null +++ b/libcxx/test/thread/futures/futures.promise/set_lvalue.pass.cpp @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <future> + +// class promise<R> + +// void promise<R&>::set_value(R& r); + +#include <future> +#include <cassert> + +int main() +{ + { + typedef int& T; + int i = 3; + std::promise<T> p; + std::future<T> f = p.get_future(); + p.set_value(i); + assert(f.get() == 3); + ++i; + f = p.get_future(); + assert(f.get() == 4); + try + { + p.set_value(i); + assert(false); + } + catch (const std::future_error& e) + { + assert(e.code() == make_error_code(std::future_errc::promise_already_satisfied)); + } + } +} diff --git a/libcxx/test/thread/futures/futures.promise/set_lvalue_at_thread_exit.pass.cpp b/libcxx/test/thread/futures/futures.promise/set_lvalue_at_thread_exit.pass.cpp new file mode 100644 index 00000000000..78bf44f1c04 --- /dev/null +++ b/libcxx/test/thread/futures/futures.promise/set_lvalue_at_thread_exit.pass.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <future> + +// class promise<R> + +// void promise<R&>::set_value_at_thread_exit(R& r); + +#include <future> +#include <memory> +#include <cassert> + +int i = 0; + +void func(std::promise<int&>& p) +{ + p.set_value_at_thread_exit(i); + i = 4; +} + +int main() +{ + { + std::promise<int&> p; + std::future<int&> f = p.get_future(); + std::thread(func, std::move(p)).detach(); + assert(f.get() == 4); + } +} diff --git a/libcxx/test/thread/futures/futures.promise/set_rvalue.pass.cpp b/libcxx/test/thread/futures/futures.promise/set_rvalue.pass.cpp new file mode 100644 index 00000000000..50c587bcbbe --- /dev/null +++ b/libcxx/test/thread/futures/futures.promise/set_rvalue.pass.cpp @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <future> + +// class promise<R> + +// void promise::set_value(R&& r); + +#include <future> +#include <memory> +#include <cassert> + +#ifdef _LIBCPP_MOVE + +struct A +{ + A() {} + A(const A&) = delete; + A(A&&) {throw 9;} +}; + +#endif // _LIBCPP_MOVE + +int main() +{ +#ifdef _LIBCPP_MOVE + { + typedef std::unique_ptr<int> T; + T i(new int(3)); + std::promise<T> p; + std::future<T> f = p.get_future(); + p.set_value(std::move(i)); + assert(*f.get() == 3); + try + { + p.set_value(std::move(i)); + assert(false); + } + catch (const std::future_error& e) + { + assert(e.code() == make_error_code(std::future_errc::promise_already_satisfied)); + } + } + { + typedef A T; + T i; + std::promise<T> p; + std::future<T> f = p.get_future(); + try + { + p.set_value(std::move(i)); + assert(false); + } + catch (int j) + { + assert(j == 9); + } + } +#endif // _LIBCPP_MOVE +} diff --git a/libcxx/test/thread/futures/futures.promise/set_rvalue_at_thread_exit.pass.cpp b/libcxx/test/thread/futures/futures.promise/set_rvalue_at_thread_exit.pass.cpp new file mode 100644 index 00000000000..6a996de0118 --- /dev/null +++ b/libcxx/test/thread/futures/futures.promise/set_rvalue_at_thread_exit.pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <future> + +// class promise<R> + +// void promise::set_value_at_thread_exit(R&& r); + +#include <future> +#include <memory> +#include <cassert> + +#ifdef _LIBCPP_MOVE + +void func(std::promise<std::unique_ptr<int>>& p) +{ + p.set_value_at_thread_exit(std::unique_ptr<int>(new int(5))); +} + +#endif // _LIBCPP_MOVE + +int main() +{ +#ifdef _LIBCPP_MOVE + { + std::promise<std::unique_ptr<int>> p; + std::future<std::unique_ptr<int>> f = p.get_future(); + std::thread(func, std::move(p)).detach(); + assert(*f.get() == 5); + } +#endif // _LIBCPP_MOVE +} diff --git a/libcxx/test/thread/futures/futures.promise/set_value_at_thread_exit_const.pass.cpp b/libcxx/test/thread/futures/futures.promise/set_value_at_thread_exit_const.pass.cpp new file mode 100644 index 00000000000..e2f600ad70c --- /dev/null +++ b/libcxx/test/thread/futures/futures.promise/set_value_at_thread_exit_const.pass.cpp @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <future> + +// class promise<R> + +// void promise::set_value_at_thread_exit(const R& r); + +#include <future> +#include <cassert> + +void func(std::promise<int>& p) +{ + const int i = 5; + p.set_value_at_thread_exit(i); +} + +int main() +{ + { + std::promise<int> p; + std::future<int> f = p.get_future(); + std::thread(func, std::move(p)).detach(); + assert(f.get() == 5); + } +} diff --git a/libcxx/test/thread/futures/futures.promise/set_value_at_thread_exit_void.pass.cpp b/libcxx/test/thread/futures/futures.promise/set_value_at_thread_exit_void.pass.cpp new file mode 100644 index 00000000000..57c48f53fa8 --- /dev/null +++ b/libcxx/test/thread/futures/futures.promise/set_value_at_thread_exit_void.pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <future> + +// class promise<R> + +// void promise<void>::set_value_at_thread_exit(); + +#include <future> +#include <memory> +#include <cassert> + +int i = 0; + +void func(std::promise<void>& p) +{ + p.set_value_at_thread_exit(); + i = 1; +} + +int main() +{ + { + std::promise<void> p; + std::future<void> f = p.get_future(); + std::thread(func, std::move(p)).detach(); + f.get(); + assert(i == 1); + } +} diff --git a/libcxx/test/thread/futures/futures.promise/set_value_const.pass.cpp b/libcxx/test/thread/futures/futures.promise/set_value_const.pass.cpp new file mode 100644 index 00000000000..29d0a6c1ea8 --- /dev/null +++ b/libcxx/test/thread/futures/futures.promise/set_value_const.pass.cpp @@ -0,0 +1,61 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <future> + +// class promise<R> + +// void promise::set_value(const R& r); + +#include <future> +#include <cassert> + +struct A +{ + A() {} + A(const A&) {throw 10;} +}; + +int main() +{ + { + typedef int T; + T i = 3; + std::promise<T> p; + std::future<T> f = p.get_future(); + p.set_value(i); + ++i; + assert(f.get() == 3); + --i; + try + { + p.set_value(i); + assert(false); + } + catch (const std::future_error& e) + { + assert(e.code() == make_error_code(std::future_errc::promise_already_satisfied)); + } + } + { + typedef A T; + T i; + std::promise<T> p; + std::future<T> f = p.get_future(); + try + { + p.set_value(i); + assert(false); + } + catch (int j) + { + assert(j == 10); + } + } +} diff --git a/libcxx/test/thread/futures/futures.promise/set_value_void.pass.cpp b/libcxx/test/thread/futures/futures.promise/set_value_void.pass.cpp new file mode 100644 index 00000000000..eeaad30f558 --- /dev/null +++ b/libcxx/test/thread/futures/futures.promise/set_value_void.pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <future> + +// class promise<R> + +// void promise<void>::set_value(); + +#include <future> +#include <cassert> + +int main() +{ + { + typedef void T; + std::promise<T> p; + std::future<T> f = p.get_future(); + p.set_value(); + f.get(); + try + { + p.set_value(); + assert(false); + } + catch (const std::future_error& e) + { + assert(e.code() == make_error_code(std::future_errc::promise_already_satisfied)); + } + } +} diff --git a/libcxx/test/thread/futures/futures.promise/swap.pass.cpp b/libcxx/test/thread/futures/futures.promise/swap.pass.cpp new file mode 100644 index 00000000000..4a7f148d15e --- /dev/null +++ b/libcxx/test/thread/futures/futures.promise/swap.pass.cpp @@ -0,0 +1,82 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <future> + +// class promise<R> + +// void swap(promise& other); + +// template <class R> void swap(promise<R>& x, promise<R>& y); + +#include <future> +#include <cassert> + +#include "../test_allocator.h" + +int main() +{ + assert(test_alloc_base::count == 0); + { + std::promise<int> p0(std::allocator_arg, test_allocator<int>()); + std::promise<int> p(std::allocator_arg, test_allocator<int>()); + assert(test_alloc_base::count == 2); + p.swap(p0); + assert(test_alloc_base::count == 2); + std::future<int> f = p.get_future(); + assert(test_alloc_base::count == 2); + assert(f.valid()); + f = p0.get_future(); + assert(f.valid()); + assert(test_alloc_base::count == 2); + } + assert(test_alloc_base::count == 0); + { + std::promise<int> p0(std::allocator_arg, test_allocator<int>()); + std::promise<int> p(std::allocator_arg, test_allocator<int>()); + assert(test_alloc_base::count == 2); + swap(p, p0); + assert(test_alloc_base::count == 2); + std::future<int> f = p.get_future(); + assert(test_alloc_base::count == 2); + assert(f.valid()); + f = p0.get_future(); + assert(f.valid()); + assert(test_alloc_base::count == 2); + } + assert(test_alloc_base::count == 0); + { + std::promise<int> p0(std::allocator_arg, test_allocator<int>()); + std::promise<int> p; + assert(test_alloc_base::count == 1); + p.swap(p0); + assert(test_alloc_base::count == 1); + std::future<int> f = p.get_future(); + assert(test_alloc_base::count == 1); + assert(f.valid()); + f = p0.get_future(); + assert(f.valid()); + assert(test_alloc_base::count == 1); + } + assert(test_alloc_base::count == 0); + { + std::promise<int> p0(std::allocator_arg, test_allocator<int>()); + std::promise<int> p; + assert(test_alloc_base::count == 1); + swap(p, p0); + assert(test_alloc_base::count == 1); + std::future<int> f = p.get_future(); + assert(test_alloc_base::count == 1); + assert(f.valid()); + f = p0.get_future(); + assert(f.valid()); + assert(test_alloc_base::count == 1); + } + assert(test_alloc_base::count == 0); +} diff --git a/libcxx/test/thread/futures/futures.promise/uses_allocator.pass.cpp b/libcxx/test/thread/futures/futures.promise/uses_allocator.pass.cpp new file mode 100644 index 00000000000..0d549ed7960 --- /dev/null +++ b/libcxx/test/thread/futures/futures.promise/uses_allocator.pass.cpp @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <future> + +// class promise<R> + +// template <class R, class Alloc> +// struct uses_allocator<promise<R>, Alloc> +// : true_type { }; + +#include <future> +#include "../test_allocator.h" + +int main() +{ + static_assert((std::uses_allocator<std::promise<int>, test_allocator<int> >::value), ""); + static_assert((std::uses_allocator<std::promise<int&>, test_allocator<int> >::value), ""); + static_assert((std::uses_allocator<std::promise<void>, test_allocator<void> >::value), ""); +} diff --git a/libcxx/test/thread/futures/test_allocator.h b/libcxx/test/thread/futures/test_allocator.h new file mode 100644 index 00000000000..94a80e2db4b --- /dev/null +++ b/libcxx/test/thread/futures/test_allocator.h @@ -0,0 +1,143 @@ +#ifndef TEST_ALLOCATOR_H +#define TEST_ALLOCATOR_H + +#include <cstddef> +#include <type_traits> +#include <cstdlib> +#include <new> +#include <climits> + +class test_alloc_base +{ +public: + static int count; +public: + static int throw_after; +}; + +int test_alloc_base::count = 0; +int test_alloc_base::throw_after = INT_MAX; + +template <class T> +class test_allocator + : public test_alloc_base +{ + int data_; + + template <class U> friend class test_allocator; +public: + + typedef unsigned size_type; + typedef int difference_type; + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef typename std::add_lvalue_reference<value_type>::type reference; + typedef typename std::add_lvalue_reference<const value_type>::type const_reference; + + template <class U> struct rebind {typedef test_allocator<U> other;}; + + test_allocator() throw() : data_(-1) {} + explicit test_allocator(int i) throw() : data_(i) {} + test_allocator(const test_allocator& a) throw() + : data_(a.data_) {} + template <class U> test_allocator(const test_allocator<U>& a) throw() + : data_(a.data_) {} + ~test_allocator() throw() {data_ = 0;} + pointer address(reference x) const {return &x;} + const_pointer address(const_reference x) const {return &x;} + pointer allocate(size_type n, const void* = 0) + { + if (count >= throw_after) + throw std::bad_alloc(); + ++count; + return (pointer)std::malloc(n * sizeof(T)); + } + void deallocate(pointer p, size_type n) + {--count; std::free(p);} + size_type max_size() const throw() + {return UINT_MAX / sizeof(T);} + void construct(pointer p, const T& val) + {::new(p) T(val);} +#ifdef _LIBCPP_MOVE + void construct(pointer p, T&& val) + {::new(p) T(std::move(val));} +#endif // _LIBCPP_MOVE + void destroy(pointer p) {p->~T();} + + friend bool operator==(const test_allocator& x, const test_allocator& y) + {return x.data_ == y.data_;} + friend bool operator!=(const test_allocator& x, const test_allocator& y) + {return !(x == y);} +}; + +template <> +class test_allocator<void> + : public test_alloc_base +{ + int data_; + + template <class U> friend class test_allocator; +public: + + typedef unsigned size_type; + typedef int difference_type; + typedef void value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + + template <class U> struct rebind {typedef test_allocator<U> other;}; + + test_allocator() throw() : data_(-1) {} + explicit test_allocator(int i) throw() : data_(i) {} + test_allocator(const test_allocator& a) throw() + : data_(a.data_) {} + template <class U> test_allocator(const test_allocator<U>& a) throw() + : data_(a.data_) {} + ~test_allocator() throw() {data_ = 0;} + + friend bool operator==(const test_allocator& x, const test_allocator& y) + {return x.data_ == y.data_;} + friend bool operator!=(const test_allocator& x, const test_allocator& y) + {return !(x == y);} +}; + +template <class T> +class other_allocator +{ + int data_; + + template <class U> friend class other_allocator; + +public: + typedef T value_type; + + other_allocator() : data_(-1) {} + explicit other_allocator(int i) : data_(i) {} + template <class U> other_allocator(const other_allocator<U>& a) + : data_(a.data_) {} + T* allocate(std::size_t n) + {return (T*)std::malloc(n * sizeof(T));} + void deallocate(T* p, std::size_t n) + {std::free(p);} + + other_allocator select_on_container_copy_construction() const + {return other_allocator(-2);} + + friend bool operator==(const other_allocator& x, const other_allocator& y) + {return x.data_ == y.data_;} + friend bool operator!=(const other_allocator& x, const other_allocator& y) + {return !(x == y);} + + typedef std::true_type propagate_on_container_copy_assignment; + typedef std::true_type propagate_on_container_move_assignment; + typedef std::true_type propagate_on_container_swap; + +#ifdef _LIBCPP_HAS_NO_ADVANCED_SFINAE + std::size_t max_size() const + {return UINT_MAX / sizeof(T);} +#endif // _LIBCPP_HAS_NO_ADVANCED_SFINAE + +}; + +#endif // TEST_ALLOCATOR_H |