summaryrefslogtreecommitdiffstats
path: root/libcxx
diff options
context:
space:
mode:
authorHoward Hinnant <hhinnant@apple.com>2010-08-28 21:01:06 +0000
committerHoward Hinnant <hhinnant@apple.com>2010-08-28 21:01:06 +0000
commit8759d9d4d018351172b30dd41bdcbbe40af86ed8 (patch)
tree51b40ea60171bc659a2dbcc8f1af79f3acbe5089 /libcxx
parent7a05e6dca2c87f9b5294acec50ac59db9a97acb7 (diff)
downloadbcm5719-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')
-rw-r--r--libcxx/include/future111
-rw-r--r--libcxx/test/thread/futures/futures.promise/alloc_ctor.pass.cpp49
-rw-r--r--libcxx/test/thread/futures/futures.promise/copy_assign.fail.cpp87
-rw-r--r--libcxx/test/thread/futures/futures.promise/copy_ctor.fail.cpp81
-rw-r--r--libcxx/test/thread/futures/futures.promise/default.pass.cpp36
-rw-r--r--libcxx/test/thread/futures/futures.promise/dtor.pass.cpp106
-rw-r--r--libcxx/test/thread/futures/futures.promise/move_assign.pass.cpp89
-rw-r--r--libcxx/test/thread/futures/futures.promise/move_ctor.pass.cpp83
-rw-r--r--libcxx/test/thread/futures/futures.promise/set_exception.pass.cpp45
-rw-r--r--libcxx/test/thread/futures/futures.promise/set_exception_at_thread_exit.pass.cpp42
-rw-r--r--libcxx/test/thread/futures/futures.promise/set_lvalue.pass.cpp41
-rw-r--r--libcxx/test/thread/futures/futures.promise/set_lvalue_at_thread_exit.pass.cpp36
-rw-r--r--libcxx/test/thread/futures/futures.promise/set_rvalue.pass.cpp67
-rw-r--r--libcxx/test/thread/futures/futures.promise/set_rvalue_at_thread_exit.pass.cpp39
-rw-r--r--libcxx/test/thread/futures/futures.promise/set_value_at_thread_exit_const.pass.cpp33
-rw-r--r--libcxx/test/thread/futures/futures.promise/set_value_at_thread_exit_void.pass.cpp37
-rw-r--r--libcxx/test/thread/futures/futures.promise/set_value_const.pass.cpp61
-rw-r--r--libcxx/test/thread/futures/futures.promise/set_value_void.pass.cpp37
-rw-r--r--libcxx/test/thread/futures/futures.promise/swap.pass.cpp82
-rw-r--r--libcxx/test/thread/futures/futures.promise/uses_allocator.pass.cpp26
-rw-r--r--libcxx/test/thread/futures/test_allocator.h143
21 files changed, 1329 insertions, 2 deletions
diff --git a/libcxx/include/future b/libcxx/include/future
index a8b02a6d63c..abfb77d020f 100644
--- a/libcxx/include/future
+++ b/libcxx/include/future
@@ -576,6 +576,28 @@ public:
wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const;
};
+template <class _Clock, class _Duration>
+future_status
+__assoc_sub_state::wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const
+{
+ unique_lock<mutex> __lk(__mut_);
+ while (!(__state_ & (ready | deferred)) && _Clock::now() < __abs_time)
+ __cv_.wait_until(__lk, __abs_time);
+ if (__state_ & ready)
+ return future_status::ready;
+ if (__state_ & deferred)
+ return future_status::deferred;
+ return future_status::timeout;
+}
+
+template <class _Rep, class _Period>
+inline _LIBCPP_INLINE_VISIBILITY
+future_status
+__assoc_sub_state::wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const
+{
+ return wait_until(chrono::monotonic_clock::now() + __rel_time);
+}
+
template <class _R>
class __assoc_state
: public __assoc_sub_state
@@ -675,6 +697,69 @@ __assoc_state<_R>::copy()
return *reinterpret_cast<_R*>(&__value_);
}
+template <class _R>
+class __assoc_state<_R&>
+ : public __assoc_sub_state
+{
+ typedef __assoc_sub_state base;
+ typedef _R* _U;
+protected:
+ _U __value_;
+
+ virtual void __on_zero_shared();
+public:
+
+ void set_value(_R& __arg);
+ void set_value_at_thread_exit(_R& __arg);
+
+ _R& copy();
+};
+
+template <class _R>
+void
+__assoc_state<_R&>::__on_zero_shared()
+{
+ delete this;
+}
+
+template <class _R>
+void
+__assoc_state<_R&>::set_value(_R& __arg)
+{
+ unique_lock<mutex> __lk(this->__mut_);
+ if (this->__has_value())
+ throw future_error(make_error_code(future_errc::promise_already_satisfied));
+ __value_ = &__arg;
+ this->__state_ |= base::__constructed | base::ready;
+ __lk.unlock();
+ __cv_.notify_all();
+}
+
+template <class _R>
+void
+__assoc_state<_R&>::set_value_at_thread_exit(_R& __arg)
+{
+ unique_lock<mutex> __lk(this->__mut_);
+ if (this->__has_value())
+ throw future_error(make_error_code(future_errc::promise_already_satisfied));
+ __value_ = &__arg;
+ this->__state_ |= base::__constructed;
+ __thread_local_data->__make_ready_at_thread_exit(this);
+ __lk.unlock();
+}
+
+template <class _R>
+_R&
+__assoc_state<_R&>::copy()
+{
+ unique_lock<mutex> __lk(this->__mut_);
+ while (!this->__is_ready())
+ this->__cv_.wait(__lk);
+ if (this->__exception_ != nullptr)
+ rethrow_exception(this->__exception_);
+ return *__value_;
+}
+
template <class _R, class _Alloc>
class __assoc_state_alloc
: public __assoc_state<_R>
@@ -699,6 +784,28 @@ __assoc_state_alloc<_R, _Alloc>::__on_zero_shared()
__a.deallocate(this, 1);
}
+template <class _R, class _Alloc>
+class __assoc_state_alloc<_R&, _Alloc>
+ : public __assoc_state<_R&>
+{
+ typedef __assoc_state<_R&> base;
+ _Alloc __alloc_;
+
+ virtual void __on_zero_shared();
+public:
+ explicit __assoc_state_alloc(const _Alloc& __a)
+ : __alloc_(__a) {}
+};
+
+template <class _R, class _Alloc>
+void
+__assoc_state_alloc<_R&, _Alloc>::__on_zero_shared()
+{
+ typename _Alloc::template rebind<__assoc_state_alloc>::other __a(__alloc_);
+ this->~__assoc_state_alloc();
+ __a.deallocate(this, 1);
+}
+
template <class _Alloc>
class __assoc_sub_state_alloc
: public __assoc_sub_state
@@ -717,7 +824,7 @@ void
__assoc_sub_state_alloc<_Alloc>::__on_zero_shared()
{
this->~base();
- typename _Alloc::template rebind<__assoc_state_alloc>::other __a(__alloc_);
+ typename _Alloc::template rebind<__assoc_sub_state_alloc>::other __a(__alloc_);
this->~__assoc_sub_state_alloc();
__a.deallocate(this, 1);
}
@@ -865,7 +972,7 @@ template <class _R>
_R&
future<_R&>::get()
{
- __assoc_state<_R>* __s = __state_;
+ __assoc_state<_R&>* __s = __state_;
__state_ = nullptr;
return __s->copy();
}
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
OpenPOWER on IntegriCloud