[cfe-commits] [libcxx] r112500 - in /libcxx/trunk: include/ src/ test/thread/futures/futures.async/ test/thread/futures/futures.promise/ test/thread/futures/futures.tas/ test/thread/futures/futures.tas/futures.taask.nonmembers/ test/thread/futures/futures.tas/futures.task.members/ test/thread/futures/futures.tas/futures.task.nonmembers/

Howard Hinnant hhinnant at apple.com
Mon Aug 30 11:46:22 PDT 2010


Author: hhinnant
Date: Mon Aug 30 13:46:21 2010
New Revision: 112500

URL: http://llvm.org/viewvc/llvm-project?rev=112500&view=rev
Log:
[futures.task] and [futures.async].  Requires variadics and rvalue-ref support.

Added:
    libcxx/trunk/test/thread/futures/futures.async/async.pass.cpp
    libcxx/trunk/test/thread/futures/futures.promise/get_future.pass.cpp
    libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/assign_copy.fail.cpp
    libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/assign_move.pass.cpp
    libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_copy.fail.cpp
    libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_default.pass.cpp
    libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_func.pass.cpp
    libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_func_alloc.pass.cpp
    libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_move.pass.cpp
    libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/dtor.pass.cpp
    libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/get_future.pass.cpp
    libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/make_ready_at_thread_exit.pass.cpp
    libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/operator.pass.cpp
    libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/reset.pass.cpp
    libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/swap.pass.cpp
    libcxx/trunk/test/thread/futures/futures.tas/futures.task.nonmembers/
      - copied from r112391, libcxx/trunk/test/thread/futures/futures.tas/futures.taask.nonmembers/
    libcxx/trunk/test/thread/futures/futures.tas/futures.task.nonmembers/swap.pass.cpp
    libcxx/trunk/test/thread/futures/futures.tas/futures.task.nonmembers/uses_allocator.pass.cpp
    libcxx/trunk/test/thread/futures/futures.tas/types.pass.cpp
Removed:
    libcxx/trunk/test/thread/futures/futures.tas/futures.taask.nonmembers/
Modified:
    libcxx/trunk/include/future
    libcxx/trunk/src/future.cpp
    libcxx/trunk/test/thread/futures/futures.promise/set_lvalue.pass.cpp

Modified: libcxx/trunk/include/future
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/future?rev=112500&r1=112499&r2=112500&view=diff
==============================================================================
--- libcxx/trunk/include/future (original)
+++ libcxx/trunk/include/future Mon Aug 30 13:46:21 2010
@@ -399,11 +399,6 @@
     // construction and destruction
     packaged_task();
     template <class F>
-        explicit packaged_task(F f);
-    template <class F, class Allocator>
-        explicit packaged_task(allocator_arg_t, const Allocator& a, F f);
-    explicit packaged_task(R(*f)(ArgTypes...));
-    template <class F>
         explicit packaged_task(F&& f);
     template <class F, class Allocator>
         explicit packaged_task(allocator_arg_t, const Allocator& a, F&& f);
@@ -538,7 +533,7 @@
     unsigned __state_;
 
     virtual void __on_zero_shared();
-
+    void __sub_wait(unique_lock<mutex>& __lk);
 public:
     enum
     {
@@ -556,6 +551,8 @@
     void __set_future_attached() {__state_ |= __future_attached;}
     bool __has_future_attached() const {return __state_ & __future_attached;}
 
+    void __set_deferred() {__state_ |= deferred;}
+
     void __make_ready();
     bool __is_ready() const {return __state_ & ready;}
 
@@ -567,13 +564,15 @@
 
     void copy();
 
-    void wait() const;
+    void wait();
     template <class _Rep, class _Period>
         future_status
         wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const;
     template <class _Clock, class _Duration>
         future_status
         wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const;
+
+    virtual void __execute();
 };
 
 template <class _Clock, class _Duration>
@@ -581,12 +580,12 @@
 __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)
+    if (__state_ & deferred)
+        return future_status::deferred;
+    while (!(__state_ & ready) && _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;
 }
 
@@ -678,8 +677,7 @@
 __assoc_state<_R>::move()
 {
     unique_lock<mutex> __lk(this->__mut_);
-    while (!this->__is_ready())
-        this->__cv_.wait(__lk);
+    this->__sub_wait(__lk);
     if (this->__exception_ != nullptr)
         rethrow_exception(this->__exception_);
     return _STD::move(*reinterpret_cast<_R*>(&__value_));
@@ -690,8 +688,7 @@
 __assoc_state<_R>::copy()
 {
     unique_lock<mutex> __lk(this->__mut_);
-    while (!this->__is_ready())
-        this->__cv_.wait(__lk);
+    this->__sub_wait(__lk);
     if (this->__exception_ != nullptr)
         rethrow_exception(this->__exception_);
     return *reinterpret_cast<_R*>(&__value_);
@@ -753,8 +750,7 @@
 __assoc_state<_R&>::copy()
 {
     unique_lock<mutex> __lk(this->__mut_);
-    while (!this->__is_ready())
-        this->__cv_.wait(__lk);
+    this->__sub_wait(__lk);
     if (this->__exception_ != nullptr)
         rethrow_exception(this->__exception_);
     return *__value_;
@@ -829,10 +825,113 @@
     __a.deallocate(this, 1);
 }
 
+template <class _R, class _F>
+class __deferred_assoc_state
+    : public __assoc_state<_R>
+{
+    typedef __assoc_state<_R> base;
+
+    _F __func_;
+
+public:
+#ifdef _LIBCPP_MOVE
+    explicit __deferred_assoc_state(_F&& __f);
+#endif
+
+    virtual void __execute();
+};
+
+#ifdef _LIBCPP_MOVE
+
+template <class _R, class _F>
+inline _LIBCPP_INLINE_VISIBILITY
+__deferred_assoc_state<_R, _F>::__deferred_assoc_state(_F&& __f)
+    : __func_(_STD::forward<_F>(__f))
+{
+    this->__set_deferred();
+}
+
+#endif  // _LIBCPP_MOVE
+
+template <class _R, class _F>
+void
+__deferred_assoc_state<_R, _F>::__execute()
+{
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    try
+    {
+#endif  // _LIBCPP_NO_EXCEPTIONS
+        this->set_value(__func_());
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    }
+    catch (...)
+    {
+        this->set_exception(current_exception());
+    }
+#endif  // _LIBCPP_NO_EXCEPTIONS
+}
+
+template <class _F>
+class __deferred_assoc_state<void, _F>
+    : public __assoc_sub_state
+{
+    typedef __assoc_sub_state base;
+
+    _F __func_;
+
+public:
+#ifdef _LIBCPP_MOVE
+    explicit __deferred_assoc_state(_F&& __f);
+#endif
+
+    virtual void __execute();
+};
+
+#ifdef _LIBCPP_MOVE
+
+template <class _F>
+inline _LIBCPP_INLINE_VISIBILITY
+__deferred_assoc_state<void, _F>::__deferred_assoc_state(_F&& __f)
+    : __func_(_STD::forward<_F>(__f))
+{
+    this->__set_deferred();
+}
+
+#endif  // _LIBCPP_MOVE
+
+template <class _F>
+void
+__deferred_assoc_state<void, _F>::__execute()
+{
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    try
+    {
+#endif  // _LIBCPP_NO_EXCEPTIONS
+        __func_();
+        this->set_value();
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    }
+    catch (...)
+    {
+        this->set_exception(current_exception());
+    }
+#endif  // _LIBCPP_NO_EXCEPTIONS
+}
+
 template <class> class promise;
 
 // future
 
+template <class _R> class future;
+
+template <class _R, class _F>
+future<_R>
+#ifdef _LIBCPP_MOVE
+__make_deferred_assoc_state(_F&& __f);
+#else
+__make_deferred_assoc_state(_F __f);
+#endif
+
 template <class _R>
 class future
 {
@@ -841,6 +940,14 @@
     explicit future(__assoc_state<_R>* __state);
 
     template <class> friend class promise;
+
+    template <class _R1, class _F>
+#ifdef _LIBCPP_MOVE
+        friend future<_R1> __make_deferred_assoc_state(_F&& __f);
+#else
+        friend future<_R1> __make_deferred_assoc_state(_F __f);
+#endif
+
 public:
     future() : __state_(nullptr) {}
 #ifdef _LIBCPP_MOVE
@@ -887,8 +994,14 @@
     if (__state_->__has_future_attached())
         throw future_error(make_error_code(future_errc::future_already_retrieved));
     __state_->__add_shared();
+    __state_->__set_future_attached();
 }
 
+struct __release_shared_count
+{
+    void operator()(__shared_count* p) {p->__release_shared();}
+};
+
 template <class _R>
 future<_R>::~future()
 {
@@ -900,6 +1013,7 @@
 _R
 future<_R>::get()
 {
+    unique_ptr<__shared_count, __release_shared_count> __(__state_);
     __assoc_state<_R>* __s = __state_;
     __state_ = nullptr;
     return __s->move();
@@ -913,6 +1027,14 @@
     explicit future(__assoc_state<_R&>* __state);
 
     template <class> friend class promise;
+
+    template <class _R1, class _F>
+#ifdef _LIBCPP_MOVE
+        friend future<_R1> __make_deferred_assoc_state(_F&& __f);
+#else
+        friend future<_R1> __make_deferred_assoc_state(_F __f);
+#endif
+
 public:
     future() : __state_(nullptr) {}
 #ifdef _LIBCPP_MOVE
@@ -959,6 +1081,7 @@
     if (__state_->__has_future_attached())
         throw future_error(make_error_code(future_errc::future_already_retrieved));
     __state_->__add_shared();
+    __state_->__set_future_attached();
 }
 
 template <class _R>
@@ -972,6 +1095,7 @@
 _R&
 future<_R&>::get()
 {
+    unique_ptr<__shared_count, __release_shared_count> __(__state_);
     __assoc_state<_R&>* __s = __state_;
     __state_ = nullptr;
     return __s->copy();
@@ -985,6 +1109,14 @@
     explicit future(__assoc_sub_state* __state);
 
     template <class> friend class promise;
+
+    template <class _R1, class _F>
+#ifdef _LIBCPP_MOVE
+        friend future<_R1> __make_deferred_assoc_state(_F&& __f);
+#else
+        friend future<_R1> __make_deferred_assoc_state(_F __f);
+#endif
+
 public:
     future() : __state_(nullptr) {}
 #ifdef _LIBCPP_MOVE
@@ -1026,10 +1158,16 @@
 
 // promise<R>
 
+template <class> class packaged_task;
+
 template <class _R>
 class promise
 {
     __assoc_state<_R>* __state_;
+
+    explicit promise(nullptr_t) : __state_(nullptr) {}
+
+    template <class> friend class packaged_task;
 public:
     promise();
     template <class _Alloc>
@@ -1186,6 +1324,11 @@
 class promise<_R&>
 {
     __assoc_state<_R&>* __state_;
+
+    explicit promise(nullptr_t) : __state_(nullptr) {}
+
+    template <class> friend class packaged_task;
+
 public:
     promise();
     template <class _Allocator>
@@ -1310,6 +1453,11 @@
 class promise<void>
 {
     __assoc_sub_state* __state_;
+
+    explicit promise(nullptr_t) : __state_(nullptr) {}
+
+    template <class> friend class packaged_task;
+
 public:
     promise();
     template <class _Allocator>
@@ -1374,6 +1522,534 @@
 template <class _R, class _Alloc>
     struct uses_allocator<promise<_R>, _Alloc> : public true_type {};
 
+#ifndef _LIBCPP_HAS_NO_VARIADICS
+
+// packaged_task
+
+template<class _Fp> class __packaged_task_base;
+
+template<class _R, class ..._ArgTypes>
+class __packaged_task_base<_R(_ArgTypes...)>
+{
+    __packaged_task_base(const __packaged_task_base&);
+    __packaged_task_base& operator=(const __packaged_task_base&);
+public:
+    __packaged_task_base() {}
+    virtual ~__packaged_task_base() {}
+    virtual void __move_to(__packaged_task_base*) = 0;
+    virtual void destroy() = 0;
+    virtual void destroy_deallocate() = 0;
+    virtual _R operator()(_ArgTypes&& ...) = 0;
+};
+
+template<class _FD, class _Alloc, class _FB> class __packaged_task_func;
+
+template<class _F, class _Alloc, class _R, class ..._ArgTypes>
+class __packaged_task_func<_F, _Alloc, _R(_ArgTypes...)>
+    : public  __packaged_task_base<_R(_ArgTypes...)>
+{
+    __compressed_pair<_F, _Alloc> __f_;
+public:
+    explicit __packaged_task_func(const _F& __f) : __f_(__f) {}
+    explicit __packaged_task_func(_F&& __f) : __f_(_STD::move(__f)) {}
+    __packaged_task_func(const _F& __f, const _Alloc& __a)
+        : __f_(__f, __a) {}
+    __packaged_task_func(_F&& __f, const _Alloc& __a)
+        : __f_(_STD::move(__f), __a) {}
+    virtual void __move_to(__packaged_task_base<_R(_ArgTypes...)>*);
+    virtual void destroy();
+    virtual void destroy_deallocate();
+    virtual _R operator()(_ArgTypes&& ... __args);
+};
+
+template<class _F, class _Alloc, class _R, class ..._ArgTypes>
+void
+__packaged_task_func<_F, _Alloc, _R(_ArgTypes...)>::__move_to(
+                              __packaged_task_base<_R(_ArgTypes...)>* __p)
+{
+    ::new (__p) __packaged_task_func(_STD::move(__f_.first()), _STD::move(__f_.second()));
+}
+
+template<class _F, class _Alloc, class _R, class ..._ArgTypes>
+void
+__packaged_task_func<_F, _Alloc, _R(_ArgTypes...)>::destroy()
+{
+    __f_.~__compressed_pair<_F, _Alloc>();
+}
+
+template<class _F, class _Alloc, class _R, class ..._ArgTypes>
+void
+__packaged_task_func<_F, _Alloc, _R(_ArgTypes...)>::destroy_deallocate()
+{
+    typedef typename _Alloc::template rebind<__packaged_task_func>::other _A;
+    _A __a(__f_.second());
+    __f_.~__compressed_pair<_F, _Alloc>();
+    __a.deallocate(this, 1);
+}
+
+template<class _F, class _Alloc, class _R, class ..._ArgTypes>
+_R
+__packaged_task_func<_F, _Alloc, _R(_ArgTypes...)>::operator()(_ArgTypes&& ... __arg)
+{
+    return __invoke(__f_.first(), _STD::forward<_ArgTypes>(__arg)...);
+}
+
+template <class> class __packaged_task_function;
+
+template<class _R, class ..._ArgTypes>
+class __packaged_task_function<_R(_ArgTypes...)>
+{
+    typedef __packaged_task_base<_R(_ArgTypes...)> __base;
+    aligned_storage<3*sizeof(void*)>::type __buf_;
+    __base* __f_;
+
+public:
+    typedef _R result_type;
+
+    // construct/copy/destroy:
+    __packaged_task_function() : __f_(nullptr) {}
+    template<class _F>
+      __packaged_task_function(_F&& __f);
+    template<class _F, class _Alloc>
+      __packaged_task_function(allocator_arg_t, const _Alloc& __a, _F&& __f);
+
+    __packaged_task_function(__packaged_task_function&&);
+    __packaged_task_function& operator=(__packaged_task_function&&);
+
+    __packaged_task_function(const __packaged_task_function&) =  delete;
+    __packaged_task_function& operator=(const __packaged_task_function&) =  delete;
+
+    ~__packaged_task_function();
+
+    void swap(__packaged_task_function&);
+
+    _R operator()(_ArgTypes...) const;
+};
+
+template<class _R, class ..._ArgTypes>
+__packaged_task_function<_R(_ArgTypes...)>::__packaged_task_function(__packaged_task_function&& __f)
+{
+    if (__f.__f_ == nullptr)
+        __f_ = nullptr;
+    else if (__f.__f_ == (__base*)&__f.__buf_)
+    {
+        __f_ = (__base*)&__buf_;
+        __f.__f_->__move_to(__f_);
+    }
+    else
+    {
+        __f_ = __f.__f_;
+        __f.__f_ = nullptr;
+    }
+}
+
+template<class _R, class ..._ArgTypes>
+template <class _F>
+__packaged_task_function<_R(_ArgTypes...)>::__packaged_task_function(_F&& __f)
+    : __f_(nullptr)
+{
+    typedef typename remove_reference<_F>::type _FR;
+    typedef __packaged_task_func<_FR, allocator<_FR>, _R(_ArgTypes...)> _FF;
+    if (sizeof(_FF) <= sizeof(__buf_))
+    {
+        __f_ = (__base*)&__buf_;
+        ::new (__f_) _FF(_STD::forward<_F>(__f));
+    }
+    else
+    {
+        typedef allocator<_FF> _A;
+        _A __a;
+        typedef __allocator_destructor<_A> _D;
+        unique_ptr<__base, _D> __hold(__a.allocate(1), _D(__a, 1));
+        ::new (__hold.get()) _FF(_STD::forward<_F>(__f), allocator<_FR>(__a));
+        __f_ = __hold.release();
+    }
+}
+
+template<class _R, class ..._ArgTypes>
+template <class _F, class _Alloc>
+__packaged_task_function<_R(_ArgTypes...)>::__packaged_task_function(
+                                  allocator_arg_t, const _Alloc& __a0, _F&& __f)
+    : __f_(nullptr)
+{
+    typedef allocator_traits<_Alloc> __alloc_traits;
+    typedef typename remove_reference<_F>::type _FR;
+    typedef __packaged_task_func<_FR, _Alloc, _R(_ArgTypes...)> _FF;
+    if (sizeof(_FF) <= sizeof(__buf_))
+    {
+        __f_ = (__base*)&__buf_;
+        ::new (__f_) _FF(_STD::forward<_F>(__f));
+    }
+    else
+    {
+        typedef typename __alloc_traits::template
+#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
+            rebind_alloc<_FF>
+#else
+            rebind_alloc<_FF>::other
+#endif
+                                                     _A;
+        _A __a(__a0);
+        typedef __allocator_destructor<_A> _D;
+        unique_ptr<__base, _D> __hold(__a.allocate(1), _D(__a, 1));
+        ::new (__hold.get()) _FF(_STD::forward<_F>(__f), _Alloc(__a));
+        __f_ = __hold.release();
+    }
+}
+
+template<class _R, class ..._ArgTypes>
+__packaged_task_function<_R(_ArgTypes...)>&
+__packaged_task_function<_R(_ArgTypes...)>::operator=(__packaged_task_function&& __f)
+{
+    if (__f_ == (__base*)&__buf_)
+        __f_->destroy();
+    else if (__f_)
+        __f_->destroy_deallocate();
+    __f_ = nullptr;
+    if (__f.__f_ == nullptr)
+        __f_ = nullptr;
+    else if (__f.__f_ == (__base*)&__f.__buf_)
+    {
+        __f_ = (__base*)&__buf_;
+        __f.__f_->__move_to(__f_);
+    }
+    else
+    {
+        __f_ = __f.__f_;
+        __f.__f_ = nullptr;
+    }
+}
+
+template<class _R, class ..._ArgTypes>
+__packaged_task_function<_R(_ArgTypes...)>::~__packaged_task_function()
+{
+    if (__f_ == (__base*)&__buf_)
+        __f_->destroy();
+    else if (__f_)
+        __f_->destroy_deallocate();
+}
+
+template<class _R, class ..._ArgTypes>
+void
+__packaged_task_function<_R(_ArgTypes...)>::swap(__packaged_task_function& __f)
+{
+    if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_)
+    {
+        typename aligned_storage<sizeof(__buf_)>::type __tempbuf;
+        __base* __t = (__base*)&__tempbuf;
+        __f_->__move_to(__t);
+        __f_->destroy();
+        __f_ = nullptr;
+        __f.__f_->__move_to((__base*)&__buf_);
+        __f.__f_->destroy();
+        __f.__f_ = nullptr;
+        __f_ = (__base*)&__buf_;
+        __t->__move_to((__base*)&__f.__buf_);
+        __t->destroy();
+        __f.__f_ = (__base*)&__f.__buf_;
+    }
+    else if (__f_ == (__base*)&__buf_)
+    {
+        __f_->__move_to((__base*)&__f.__buf_);
+        __f_->destroy();
+        __f_ = __f.__f_;
+        __f.__f_ = (__base*)&__f.__buf_;
+    }
+    else if (__f.__f_ == (__base*)&__f.__buf_)
+    {
+        __f.__f_->__move_to((__base*)&__buf_);
+        __f.__f_->destroy();
+        __f.__f_ = __f_;
+        __f_ = (__base*)&__buf_;
+    }
+    else
+        _STD::swap(__f_, __f.__f_);
+}
+
+template<class _R, class ..._ArgTypes>
+inline _LIBCPP_INLINE_VISIBILITY
+_R
+__packaged_task_function<_R(_ArgTypes...)>::operator()(_ArgTypes... __arg) const
+{
+    return (*__f_)(_STD::forward<_ArgTypes>(__arg)...);
+}
+
+template<class _R, class ..._ArgTypes>
+class packaged_task<_R(_ArgTypes...)>
+{
+public:
+    typedef _R result_type;
+
+private:
+    __packaged_task_function<result_type(_ArgTypes...)> __f_;
+    promise<result_type>                                __p_;
+
+public:
+    // construction and destruction
+    packaged_task() : __p_(nullptr) {}
+    template <class _F>
+        explicit packaged_task(_F&& __f) : __f_(_STD::forward<_F>(__f)) {}
+    template <class _F, class _Allocator>
+        explicit packaged_task(allocator_arg_t, const _Allocator& __a, _F&& __f)
+             : __f_(allocator_arg, __a, _STD::forward<_F>(__f)),
+               __p_(allocator_arg, __a) {}
+    // ~packaged_task() = default;
+
+    // no copy
+    packaged_task(packaged_task&) = delete;
+    packaged_task& operator=(packaged_task&) = delete;
+
+    // move support
+    packaged_task(packaged_task&& __other)
+        : __f_(_STD::move(__other.__f_)), __p_(_STD::move(__other.__p_)) {}
+    packaged_task& operator=(packaged_task&& __other)
+    {
+        __f_ = _STD::move(__other.__f_);
+        __p_ = _STD::move(__other.__p_);
+        return *this;
+    }
+    void swap(packaged_task& __other)
+    {
+        __f_.swap(__other.__f_);
+        __p_.swap(__other.__p_);
+    }
+
+    //explicit
+        operator bool() const {return __p_.__state_ != nullptr;}
+
+    // result retrieval
+    future<result_type> get_future() {return __p_.get_future();}
+
+    // execution
+    void operator()(_ArgTypes... __args);
+    void make_ready_at_thread_exit(_ArgTypes... __args);
+
+    void reset();
+};
+
+template<class _R, class ..._ArgTypes>
+void
+packaged_task<_R(_ArgTypes...)>::operator()(_ArgTypes... __args)
+{
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    if (__p_.__state_ == nullptr)
+        throw future_error(make_error_code(future_errc::no_state));
+    if (__p_.__state_->__has_value())
+        throw future_error(make_error_code(future_errc::promise_already_satisfied));
+    try
+    {
+#endif  // _LIBCPP_NO_EXCEPTIONS
+        __p_.set_value(__f_(_STD::forward<_ArgTypes>(__args)...));
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    }
+    catch (...)
+    {
+        __p_.set_exception(current_exception());
+    }
+#endif  // _LIBCPP_NO_EXCEPTIONS
+}
+
+template<class _R, class ..._ArgTypes>
+void
+packaged_task<_R(_ArgTypes...)>::make_ready_at_thread_exit(_ArgTypes... __args)
+{
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    if (__p_.__state_ == nullptr)
+        throw future_error(make_error_code(future_errc::no_state));
+    if (__p_.__state_->__has_value())
+        throw future_error(make_error_code(future_errc::promise_already_satisfied));
+    try
+    {
+#endif  // _LIBCPP_NO_EXCEPTIONS
+        __p_.set_value_at_thread_exit(__f_(_STD::forward<_ArgTypes>(__args)...));
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    }
+    catch (...)
+    {
+        __p_.set_exception_at_thread_exit(current_exception());
+    }
+#endif  // _LIBCPP_NO_EXCEPTIONS
+}
+
+template<class _R, class ..._ArgTypes>
+void
+packaged_task<_R(_ArgTypes...)>::reset()
+{
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    if (!(*this))
+        throw future_error(make_error_code(future_errc::no_state));
+#endif  // _LIBCPP_NO_EXCEPTIONS
+    __p_ = promise<result_type>();
+}
+
+template<class ..._ArgTypes>
+class packaged_task<void(_ArgTypes...)>
+{
+public:
+    typedef void result_type;
+
+private:
+    __packaged_task_function<result_type(_ArgTypes...)> __f_;
+    promise<result_type>                                __p_;
+
+public:
+    // construction and destruction
+    packaged_task() : __p_(nullptr) {}
+    template <class _F>
+        explicit packaged_task(_F&& __f) : __f_(_STD::forward<_F>(__f)) {}
+    template <class _F, class _Allocator>
+        explicit packaged_task(allocator_arg_t, const _Allocator& __a, _F&& __f)
+             : __f_(allocator_arg, __a, _STD::forward<_F>(__f)),
+               __p_(allocator_arg, __a) {}
+    // ~packaged_task() = default;
+
+    // no copy
+    packaged_task(packaged_task&) = delete;
+    packaged_task& operator=(packaged_task&) = delete;
+
+    // move support
+    packaged_task(packaged_task&& __other)
+        : __f_(_STD::move(__other.__f_)), __p_(_STD::move(__other.__p_)) {}
+    packaged_task& operator=(packaged_task&& __other)
+    {
+        __f_ = _STD::move(__other.__f_);
+        __p_ = _STD::move(__other.__p_);
+        return *this;
+    }
+    void swap(packaged_task& __other)
+    {
+        __f_.swap(__other.__f_);
+        __p_.swap(__other.__p_);
+    }
+
+    //explicit
+        operator bool() const {return __p_.__state_ != nullptr;}
+
+    // result retrieval
+    future<result_type> get_future() {return __p_.get_future();}
+
+    // execution
+    void operator()(_ArgTypes... __args);
+    void make_ready_at_thread_exit(_ArgTypes... __args);
+
+    void reset();
+};
+
+template<class ..._ArgTypes>
+void
+packaged_task<void(_ArgTypes...)>::operator()(_ArgTypes... __args)
+{
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    if (__p_.__state_ == nullptr)
+        throw future_error(make_error_code(future_errc::no_state));
+    if (__p_.__state_->__has_value())
+        throw future_error(make_error_code(future_errc::promise_already_satisfied));
+    try
+    {
+#endif  // _LIBCPP_NO_EXCEPTIONS
+        __f_(_STD::forward<_ArgTypes>(__args)...);
+        __p_.set_value();
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    }
+    catch (...)
+    {
+        __p_.set_exception(current_exception());
+    }
+#endif  // _LIBCPP_NO_EXCEPTIONS
+}
+
+template<class ..._ArgTypes>
+void
+packaged_task<void(_ArgTypes...)>::make_ready_at_thread_exit(_ArgTypes... __args)
+{
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    if (__p_.__state_ == nullptr)
+        throw future_error(make_error_code(future_errc::no_state));
+    if (__p_.__state_->__has_value())
+        throw future_error(make_error_code(future_errc::promise_already_satisfied));
+    try
+    {
+#endif  // _LIBCPP_NO_EXCEPTIONS
+        __f_(_STD::forward<_ArgTypes>(__args)...);
+        __p_.set_value_at_thread_exit();
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    }
+    catch (...)
+    {
+        __p_.set_exception_at_thread_exit(current_exception());
+    }
+#endif  // _LIBCPP_NO_EXCEPTIONS
+}
+
+template<class ..._ArgTypes>
+void
+packaged_task<void(_ArgTypes...)>::reset()
+{
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    if (!(*this))
+        throw future_error(make_error_code(future_errc::no_state));
+#endif  // _LIBCPP_NO_EXCEPTIONS
+    __p_ = promise<result_type>();
+}
+
+template <class _Callable>
+inline _LIBCPP_INLINE_VISIBILITY
+void
+swap(packaged_task<_Callable>& __x, packaged_task<_Callable>& __y)
+{
+    __x.swap(__y);
+}
+
+template <class _Callable, class _Alloc>
+struct uses_allocator<packaged_task<_Callable>, _Alloc> : public true_type {};
+
+template <class _R, class _F>
+future<_R>
+#ifdef _LIBCPP_MOVE
+__make_deferred_assoc_state(_F&& __f)
+#else
+__make_deferred_assoc_state(_F __f)
+#endif
+{
+    unique_ptr<__deferred_assoc_state<_R, _F>, __release_shared_count>
+        __h(new __deferred_assoc_state<_R, _F>(_STD::forward<_F>(__f)));
+    return future<_R>(__h.get());
+}
+
+template <class _F, class... _Args>
+future<typename result_of<_F(_Args...)>::type>
+async(launch __policy, _F&& __f, _Args&&... __args)
+{
+    typedef typename result_of<_F(_Args...)>::type _R;
+    future<_R> __r;
+    if (__policy == launch::sync)
+        __r = _STD::__make_deferred_assoc_state<_R>(bind(_STD::forward<_F>(__f),
+                                               _STD::forward<_Args>(__args)...));
+    else
+    {
+        packaged_task<_R()> __pk(bind(_STD::forward<_F>(__f),
+                                      _STD::forward<_Args>(__args)...));
+        __r = __pk.get_future();
+        thread(_STD::move(__pk)).detach();
+    }
+    return __r;
+}
+
+template <class _F, class... _Args>
+inline _LIBCPP_INLINE_VISIBILITY
+typename enable_if
+<
+    !is_same<typename decay<_F>::type, launch>::value,
+    future<typename result_of<_F(_Args...)>::type>
+>::type
+async(_F&& __f, _Args&&... __args)
+{
+    return async(launch::any, _STD::forward<_F>(__f),
+                              _STD::forward<_Args>(__args)...);
+}
+
+#endif  // _LIBCPP_HAS_NO_VARIADICS
+
 _LIBCPP_END_NAMESPACE_STD
 
 #endif  // _LIBCPP_FUTURE

Modified: libcxx/trunk/src/future.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/src/future.cpp?rev=112500&r1=112499&r2=112500&view=diff
==============================================================================
--- libcxx/trunk/src/future.cpp (original)
+++ libcxx/trunk/src/future.cpp Mon Aug 30 13:46:21 2010
@@ -124,18 +124,39 @@
 __assoc_sub_state::copy()
 {
     unique_lock<mutex> __lk(__mut_);
-    while (!__is_ready())
-        __cv_.wait(__lk);
+    __sub_wait(__lk);
     if (__exception_ != nullptr)
         rethrow_exception(__exception_);
 }
 
 void
-__assoc_sub_state::wait() const
+__assoc_sub_state::wait()
 {
     unique_lock<mutex> __lk(__mut_);
-    while (!__is_ready())
-        __cv_.wait(__lk);
+    __sub_wait(__lk);
+}
+
+void
+__assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk)
+{
+    if (!__is_ready())
+    {
+        if (__state_ & deferred)
+        {
+            __state_ &= ~deferred;
+            __lk.unlock();
+            __execute();
+        }
+        else
+            while (!__is_ready())
+                __cv_.wait(__lk);
+    }
+}
+
+void
+__assoc_sub_state::__execute()
+{
+    throw future_error(make_error_code(future_errc::no_state));
 }
 
 future<void>::future(__assoc_sub_state* __state)
@@ -144,6 +165,7 @@
     if (__state_->__has_future_attached())
         throw future_error(make_error_code(future_errc::future_already_retrieved));
     __state_->__add_shared();
+    __state_->__set_future_attached();
 }
 
 future<void>::~future()
@@ -155,9 +177,10 @@
 void
 future<void>::get()
 {
+    unique_ptr<__shared_count, __release_shared_count> __(__state_);
     __assoc_sub_state* __s = __state_;
     __state_ = nullptr;
-    return __s->copy();
+    __s->copy();
 }
 
 promise<void>::promise()

Added: libcxx/trunk/test/thread/futures/futures.async/async.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/thread/futures/futures.async/async.pass.cpp?rev=112500&view=auto
==============================================================================
--- libcxx/trunk/test/thread/futures/futures.async/async.pass.cpp (added)
+++ libcxx/trunk/test/thread/futures/futures.async/async.pass.cpp Mon Aug 30 13:46:21 2010
@@ -0,0 +1,177 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <future>
+
+// template <class F, class... Args>
+//     future<typename result_of<F(Args...)>::type>
+//     async(F&& f, Args&&... args);
+
+// template <class F, class... Args>
+//     future<typename result_of<F(Args...)>::type>
+//     async(launch policy, F&& f, Args&&... args);
+
+#include <future>
+#include <memory>
+#include <cassert>
+
+typedef std::chrono::high_resolution_clock Clock;
+typedef std::chrono::milliseconds ms;
+
+int f0()
+{
+    std::this_thread::sleep_for(ms(200));
+    return 3;
+}
+
+int i = 0;
+
+int& f1()
+{
+    std::this_thread::sleep_for(ms(200));
+    return i;
+}
+
+void f2()
+{
+    std::this_thread::sleep_for(ms(200));
+}
+
+std::unique_ptr<int> f3(int i)
+{
+    std::this_thread::sleep_for(ms(200));
+    return std::unique_ptr<int>(new int(i));
+}
+
+std::unique_ptr<int> f4(std::unique_ptr<int>&& p)
+{
+    std::this_thread::sleep_for(ms(200));
+    return std::move(p);
+}
+
+int main()
+{
+    {
+        std::future<int> f = std::async(f0);
+        std::this_thread::sleep_for(ms(300));
+        Clock::time_point t0 = Clock::now();
+        assert(f.get() == 3);
+        Clock::time_point t1 = Clock::now();
+        assert(t1-t0 < ms(100));
+    }
+    {
+        std::future<int> f = std::async(std::launch::async, f0);
+        std::this_thread::sleep_for(ms(300));
+        Clock::time_point t0 = Clock::now();
+        assert(f.get() == 3);
+        Clock::time_point t1 = Clock::now();
+        assert(t1-t0 < ms(100));
+    }
+    {
+        std::future<int> f = std::async(std::launch::any, f0);
+        std::this_thread::sleep_for(ms(300));
+        Clock::time_point t0 = Clock::now();
+        assert(f.get() == 3);
+        Clock::time_point t1 = Clock::now();
+        assert(t1-t0 < ms(100));
+    }
+    {
+        std::future<int> f = std::async(std::launch::sync, f0);
+        std::this_thread::sleep_for(ms(300));
+        Clock::time_point t0 = Clock::now();
+        assert(f.get() == 3);
+        Clock::time_point t1 = Clock::now();
+        assert(t1-t0 > ms(100));
+    }
+
+    {
+        std::future<int&> f = std::async(f1);
+        std::this_thread::sleep_for(ms(300));
+        Clock::time_point t0 = Clock::now();
+        assert(&f.get() == &i);
+        Clock::time_point t1 = Clock::now();
+        assert(t1-t0 < ms(100));
+    }
+    {
+        std::future<int&> f = std::async(std::launch::async, f1);
+        std::this_thread::sleep_for(ms(300));
+        Clock::time_point t0 = Clock::now();
+        assert(&f.get() == &i);
+        Clock::time_point t1 = Clock::now();
+        assert(t1-t0 < ms(100));
+    }
+    {
+        std::future<int&> f = std::async(std::launch::any, f1);
+        std::this_thread::sleep_for(ms(300));
+        Clock::time_point t0 = Clock::now();
+        assert(&f.get() == &i);
+        Clock::time_point t1 = Clock::now();
+        assert(t1-t0 < ms(100));
+    }
+    {
+        std::future<int&> f = std::async(std::launch::sync, f1);
+        std::this_thread::sleep_for(ms(300));
+        Clock::time_point t0 = Clock::now();
+        assert(&f.get() == &i);
+        Clock::time_point t1 = Clock::now();
+        assert(t1-t0 > ms(100));
+    }
+
+    {
+        std::future<void> f = std::async(f2);
+        std::this_thread::sleep_for(ms(300));
+        Clock::time_point t0 = Clock::now();
+        f.get();
+        Clock::time_point t1 = Clock::now();
+        assert(t1-t0 < ms(100));
+    }
+    {
+        std::future<void> f = std::async(std::launch::async, f2);
+        std::this_thread::sleep_for(ms(300));
+        Clock::time_point t0 = Clock::now();
+        f.get();
+        Clock::time_point t1 = Clock::now();
+        assert(t1-t0 < ms(100));
+    }
+    {
+        std::future<void> f = std::async(std::launch::any, f2);
+        std::this_thread::sleep_for(ms(300));
+        Clock::time_point t0 = Clock::now();
+        f.get();
+        Clock::time_point t1 = Clock::now();
+        assert(t1-t0 < ms(100));
+    }
+    {
+        std::future<void> f = std::async(std::launch::sync, f2);
+        std::this_thread::sleep_for(ms(300));
+        Clock::time_point t0 = Clock::now();
+        f.get();
+        Clock::time_point t1 = Clock::now();
+        assert(t1-t0 > ms(100));
+    }
+
+    {
+        std::future<std::unique_ptr<int>> f = std::async(f3, 3);
+        std::this_thread::sleep_for(ms(300));
+        Clock::time_point t0 = Clock::now();
+        assert(*f.get() == 3);
+        Clock::time_point t1 = Clock::now();
+        assert(t1-t0 < ms(100));
+    }
+
+    {
+        std::future<std::unique_ptr<int>> f =
+                               std::async(f4, std::unique_ptr<int>(new int(3)));
+        std::this_thread::sleep_for(ms(300));
+        Clock::time_point t0 = Clock::now();
+        assert(*f.get() == 3);
+        Clock::time_point t1 = Clock::now();
+        assert(t1-t0 < ms(100));
+    }
+}

Added: libcxx/trunk/test/thread/futures/futures.promise/get_future.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/thread/futures/futures.promise/get_future.pass.cpp?rev=112500&view=auto
==============================================================================
--- libcxx/trunk/test/thread/futures/futures.promise/get_future.pass.cpp (added)
+++ libcxx/trunk/test/thread/futures/futures.promise/get_future.pass.cpp Mon Aug 30 13:46:21 2010
@@ -0,0 +1,53 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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>
+
+// future<R> get_future();
+
+#include <future>
+#include <cassert>
+
+int main()
+{
+    {
+        std::promise<double> p;
+        std::future<double> f = p.get_future();
+        p.set_value(105.5);
+        assert(f.get() == 105.5);
+    }
+    {
+        std::promise<double> p;
+        std::future<double> f = p.get_future();
+        try
+        {
+            f = p.get_future();
+            assert(false);
+        }
+        catch (const std::future_error& e)
+        {
+            assert(e.code() ==  make_error_code(std::future_errc::future_already_retrieved));
+        }
+    }
+    {
+        std::promise<double> p;
+        std::promise<double> p0 = std::move(p);
+        try
+        {
+            std::future<double> f = p.get_future();
+            assert(false);
+        }
+        catch (const std::future_error& e)
+        {
+            assert(e.code() ==  make_error_code(std::future_errc::no_state));
+        }
+    }
+}

Modified: libcxx/trunk/test/thread/futures/futures.promise/set_lvalue.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/thread/futures/futures.promise/set_lvalue.pass.cpp?rev=112500&r1=112499&r2=112500&view=diff
==============================================================================
--- libcxx/trunk/test/thread/futures/futures.promise/set_lvalue.pass.cpp (original)
+++ libcxx/trunk/test/thread/futures/futures.promise/set_lvalue.pass.cpp Mon Aug 30 13:46:21 2010
@@ -24,10 +24,10 @@
         std::promise<T> p;
         std::future<T> f = p.get_future();
         p.set_value(i);
-        assert(f.get() == 3);
+        int& j = f.get();
+        assert(j == 3);
         ++i;
-        f = p.get_future();
-        assert(f.get() == 4);
+        assert(j == 4);
         try
         {
             p.set_value(i);

Added: libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/assign_copy.fail.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/assign_copy.fail.cpp?rev=112500&view=auto
==============================================================================
--- libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/assign_copy.fail.cpp (added)
+++ libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/assign_copy.fail.cpp Mon Aug 30 13:46:21 2010
@@ -0,0 +1,48 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <future>
+
+// class packaged_task<R(ArgTypes...)>
+
+// packaged_task& operator=(packaged_task&) = delete;
+
+#include <future>
+#include <cassert>
+
+class A
+{
+    long data_;
+
+public:
+    explicit A(long i) : data_(i) {}
+
+    long operator()(long i, long j) const {return data_ + i + j;}
+};
+
+int main()
+{
+    {
+        std::packaged_task<double(int, char)> p0(A(5));
+        std::packaged_task<double(int, char)> p;
+        p = p0;
+        assert(!p0);
+        assert(p);
+        std::future<double> f = p.get_future();
+        p(3, 'a');
+        assert(f.get() == 105.0);
+    }
+    {
+        std::packaged_task<double(int, char)> p0;
+        std::packaged_task<double(int, char)> p;
+        p = p0;
+        assert(!p0);
+        assert(!p);
+    }
+}

Added: libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/assign_move.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/assign_move.pass.cpp?rev=112500&view=auto
==============================================================================
--- libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/assign_move.pass.cpp (added)
+++ libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/assign_move.pass.cpp Mon Aug 30 13:46:21 2010
@@ -0,0 +1,48 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <future>
+
+// class packaged_task<R(ArgTypes...)>
+
+// packaged_task& operator=(packaged_task&& other);
+
+#include <future>
+#include <cassert>
+
+class A
+{
+    long data_;
+
+public:
+    explicit A(long i) : data_(i) {}
+
+    long operator()(long i, long j) const {return data_ + i + j;}
+};
+
+int main()
+{
+    {
+        std::packaged_task<double(int, char)> p0(A(5));
+        std::packaged_task<double(int, char)> p;
+        p = std::move(p0);
+        assert(!p0);
+        assert(p);
+        std::future<double> f = p.get_future();
+        p(3, 'a');
+        assert(f.get() == 105.0);
+    }
+    {
+        std::packaged_task<double(int, char)> p0;
+        std::packaged_task<double(int, char)> p;
+        p = std::move(p0);
+        assert(!p0);
+        assert(!p);
+    }
+}

Added: libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_copy.fail.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_copy.fail.cpp?rev=112500&view=auto
==============================================================================
--- libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_copy.fail.cpp (added)
+++ libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_copy.fail.cpp Mon Aug 30 13:46:21 2010
@@ -0,0 +1,46 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <future>
+
+// class packaged_task<R(ArgTypes...)>
+
+// packaged_task(packaged_task&) = delete;
+
+#include <future>
+#include <cassert>
+
+class A
+{
+    long data_;
+
+public:
+    explicit A(long i) : data_(i) {}
+
+    long operator()(long i, long j) const {return data_ + i + j;}
+};
+
+int main()
+{
+    {
+        std::packaged_task<double(int, char)> p0(A(5));
+        std::packaged_task<double(int, char)> p(p0);
+        assert(!p0);
+        assert(p);
+        std::future<double> f = p.get_future();
+        p(3, 'a');
+        assert(f.get() == 105.0);
+    }
+    {
+        std::packaged_task<double(int, char)> p0;
+        std::packaged_task<double(int, char)> p(p0);
+        assert(!p0);
+        assert(!p);
+    }
+}

Added: libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_default.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_default.pass.cpp?rev=112500&view=auto
==============================================================================
--- libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_default.pass.cpp (added)
+++ libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_default.pass.cpp Mon Aug 30 13:46:21 2010
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <future>
+
+// class packaged_task<R(ArgTypes...)>
+
+// packaged_task();
+
+#include <future>
+#include <cassert>
+
+struct A {};
+
+int main()
+{
+    std::packaged_task<A(int, char)> p;
+    assert(!p);
+}

Added: libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_func.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_func.pass.cpp?rev=112500&view=auto
==============================================================================
--- libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_func.pass.cpp (added)
+++ libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_func.pass.cpp Mon Aug 30 13:46:21 2010
@@ -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 packaged_task<R(ArgTypes...)>
+
+// template <class F>
+//     explicit packaged_task(F&& f);
+
+#include <future>
+#include <cassert>
+
+class A
+{
+    long data_;
+
+public:
+    static int n_moves;
+    static int n_copies;
+
+    explicit A(long i) : data_(i) {}
+    A(A&& a) : data_(a.data_) {++n_moves; a.data_ = -1;}
+    A(const A& a) : data_(a.data_) {++n_copies;}
+
+    long operator()(long i, long j) const {return data_ + i + j;}
+};
+
+int A::n_moves = 0;
+int A::n_copies = 0;
+
+int main()
+{
+    {
+        std::packaged_task<double(int, char)> p(A(5));
+        assert(p);
+        std::future<double> f = p.get_future();
+        p(3, 'a');
+        assert(f.get() == 105.0);
+        assert(A::n_copies == 0);
+        assert(A::n_moves > 0);
+    }
+    A::n_copies == 0;
+    A::n_copies = 0;
+    {
+        A a(5);
+        std::packaged_task<double(int, char)> p(a);
+        assert(p);
+        std::future<double> f = p.get_future();
+        p(3, 'a');
+        assert(f.get() == 105.0);
+        assert(A::n_copies > 0);
+        assert(A::n_moves > 0);
+    }
+}

Added: libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_func_alloc.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_func_alloc.pass.cpp?rev=112500&view=auto
==============================================================================
--- libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_func_alloc.pass.cpp (added)
+++ libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_func_alloc.pass.cpp Mon Aug 30 13:46:21 2010
@@ -0,0 +1,69 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <future>
+
+// class packaged_task<R(ArgTypes...)>
+
+// template <class F, class Allocator>
+//     explicit packaged_task(allocator_arg_t, const Allocator& a, F&& f);
+
+#include <future>
+#include <cassert>
+
+#include "../../test_allocator.h"
+
+class A
+{
+    long data_;
+
+public:
+    static int n_moves;
+    static int n_copies;
+
+    explicit A(long i) : data_(i) {}
+    A(A&& a) : data_(a.data_) {++n_moves; a.data_ = -1;}
+    A(const A& a) : data_(a.data_) {++n_copies;}
+
+    long operator()(long i, long j) const {return data_ + i + j;}
+};
+
+int A::n_moves = 0;
+int A::n_copies = 0;
+
+int main()
+{
+    {
+        std::packaged_task<double(int, char)> p(std::allocator_arg,
+                                                test_allocator<A>(), A(5));
+        assert(test_alloc_base::count > 0);
+        assert(p);
+        std::future<double> f = p.get_future();
+        p(3, 'a');
+        assert(f.get() == 105.0);
+        assert(A::n_copies == 0);
+        assert(A::n_moves > 0);
+    }
+    assert(test_alloc_base::count == 0);
+    A::n_copies == 0;
+    A::n_copies = 0;
+    {
+        A a(5);
+        std::packaged_task<double(int, char)> p(std::allocator_arg,
+                                                test_allocator<A>(), a);
+        assert(test_alloc_base::count > 0);
+        assert(p);
+        std::future<double> f = p.get_future();
+        p(3, 'a');
+        assert(f.get() == 105.0);
+        assert(A::n_copies > 0);
+        assert(A::n_moves > 0);
+    }
+    assert(test_alloc_base::count == 0);
+}

Added: libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_move.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_move.pass.cpp?rev=112500&view=auto
==============================================================================
--- libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_move.pass.cpp (added)
+++ libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_move.pass.cpp Mon Aug 30 13:46:21 2010
@@ -0,0 +1,46 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <future>
+
+// class packaged_task<R(ArgTypes...)>
+
+// packaged_task(packaged_task&& other);
+
+#include <future>
+#include <cassert>
+
+class A
+{
+    long data_;
+
+public:
+    explicit A(long i) : data_(i) {}
+
+    long operator()(long i, long j) const {return data_ + i + j;}
+};
+
+int main()
+{
+    {
+        std::packaged_task<double(int, char)> p0(A(5));
+        std::packaged_task<double(int, char)> p = std::move(p0);
+        assert(!p0);
+        assert(p);
+        std::future<double> f = p.get_future();
+        p(3, 'a');
+        assert(f.get() == 105.0);
+    }
+    {
+        std::packaged_task<double(int, char)> p0;
+        std::packaged_task<double(int, char)> p = std::move(p0);
+        assert(!p0);
+        assert(!p);
+    }
+}

Added: libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/dtor.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/dtor.pass.cpp?rev=112500&view=auto
==============================================================================
--- libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/dtor.pass.cpp (added)
+++ libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/dtor.pass.cpp Mon Aug 30 13:46:21 2010
@@ -0,0 +1,60 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <future>
+
+// class packaged_task<R(ArgTypes...)>
+
+// ~packaged_task();
+
+#include <future>
+#include <cassert>
+
+class A
+{
+    long data_;
+
+public:
+    explicit A(long i) : data_(i) {}
+
+    long operator()(long i, long j) const {return data_ + i + j;}
+};
+
+void func(std::packaged_task<double(int, char)>& p)
+{
+}
+
+void func2(std::packaged_task<double(int, char)>& p)
+{
+    p(3, 'a');
+}
+
+int main()
+{
+    {
+        std::packaged_task<double(int, char)> p(A(5));
+        std::future<double> f = p.get_future();
+        std::thread(func, std::move(p)).detach();
+        try
+        {
+            double i = f.get();
+            assert(false);
+        }
+        catch (const std::future_error& e)
+        {
+            assert(e.code() == make_error_code(std::future_errc::broken_promise));
+        }
+    }
+    {
+        std::packaged_task<double(int, char)> p(A(5));
+        std::future<double> f = p.get_future();
+        std::thread(func2, std::move(p)).detach();
+        assert(f.get() == 105.0);
+    }
+}

Added: libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/get_future.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/get_future.pass.cpp?rev=112500&view=auto
==============================================================================
--- libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/get_future.pass.cpp (added)
+++ libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/get_future.pass.cpp Mon Aug 30 13:46:21 2010
@@ -0,0 +1,62 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <future>
+
+// class packaged_task<R(ArgTypes...)>
+
+// future<R> get_future();
+
+#include <future>
+#include <cassert>
+
+class A
+{
+    long data_;
+
+public:
+    explicit A(long i) : data_(i) {}
+
+    long operator()(long i, long j) const {return data_ + i + j;}
+};
+
+int main()
+{
+    {
+        std::packaged_task<double(int, char)> p(A(5));
+        std::future<double> f = p.get_future();
+        p(3, 'a');
+        assert(f.get() == 105.0);
+    }
+    {
+        std::packaged_task<double(int, char)> p(A(5));
+        std::future<double> f = p.get_future();
+        try
+        {
+            f = p.get_future();
+            assert(false);
+        }
+        catch (const std::future_error& e)
+        {
+            assert(e.code() ==  make_error_code(std::future_errc::future_already_retrieved));
+        }
+    }
+    {
+        std::packaged_task<double(int, char)> p;
+        try
+        {
+            std::future<double> f = p.get_future();
+            assert(false);
+        }
+        catch (const std::future_error& e)
+        {
+            assert(e.code() ==  make_error_code(std::future_errc::no_state));
+        }
+    }
+}

Added: libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/make_ready_at_thread_exit.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/make_ready_at_thread_exit.pass.cpp?rev=112500&view=auto
==============================================================================
--- libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/make_ready_at_thread_exit.pass.cpp (added)
+++ libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/make_ready_at_thread_exit.pass.cpp Mon Aug 30 13:46:21 2010
@@ -0,0 +1,104 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <future>
+
+// class packaged_task<R(ArgTypes...)>
+
+// void make_ready_at_thread_exit(ArgTypes... args);
+
+#include <future>
+#include <cassert>
+
+class A
+{
+    long data_;
+
+public:
+    explicit A(long i) : data_(i) {}
+
+    long operator()(long i, long j) const
+    {
+        if (j == 'z')
+            throw A(6);
+        return data_ + i + j;
+    }
+};
+
+void func0(std::packaged_task<double(int, char)>& p)
+{
+    std::this_thread::sleep_for(std::chrono::milliseconds(500));
+    p.make_ready_at_thread_exit(3, 'a');
+}
+
+void func1(std::packaged_task<double(int, char)>& p)
+{
+    std::this_thread::sleep_for(std::chrono::milliseconds(500));
+    p.make_ready_at_thread_exit(3, 'z');
+}
+
+void func2(std::packaged_task<double(int, char)>& p)
+{
+    p.make_ready_at_thread_exit(3, 'a');
+    try
+    {
+        p.make_ready_at_thread_exit(3, 'c');
+    }
+    catch (const std::future_error& e)
+    {
+        assert(e.code() == make_error_code(std::future_errc::promise_already_satisfied));
+    }
+}
+
+void func3(std::packaged_task<double(int, char)>& p)
+{
+    try
+    {
+        p.make_ready_at_thread_exit(3, 'a');
+    }
+    catch (const std::future_error& e)
+    {
+        assert(e.code() == make_error_code(std::future_errc::no_state));
+    }
+}
+
+int main()
+{
+    {
+        std::packaged_task<double(int, char)> p(A(5));
+        std::future<double> f = p.get_future();
+        std::thread(func0, std::move(p)).detach();
+        assert(f.get() == 105.0);
+    }
+    {
+        std::packaged_task<double(int, char)> p(A(5));
+        std::future<double> f = p.get_future();
+        std::thread(func1, std::move(p)).detach();
+        try
+        {
+            f.get();
+            assert(false);
+        }
+        catch (const A& e)
+        {
+            assert(e(3, 'a') == 106);
+        }
+    }
+    {
+        std::packaged_task<double(int, char)> p(A(5));
+        std::future<double> f = p.get_future();
+        std::thread(func2, std::move(p)).detach();
+        assert(f.get() == 105.0);
+    }
+    {
+        std::packaged_task<double(int, char)> p;
+        std::thread t(func3, std::move(p));
+        t.join();
+    }
+}

Added: libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/operator.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/operator.pass.cpp?rev=112500&view=auto
==============================================================================
--- libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/operator.pass.cpp (added)
+++ libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/operator.pass.cpp Mon Aug 30 13:46:21 2010
@@ -0,0 +1,105 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <future>
+
+// class packaged_task<R(ArgTypes...)>
+
+// void operator()(ArgTypes... args);
+
+#include <future>
+#include <cassert>
+
+class A
+{
+    long data_;
+
+public:
+    explicit A(long i) : data_(i) {}
+
+    long operator()(long i, long j) const
+    {
+        if (j == 'z')
+            throw A(6);
+        return data_ + i + j;
+    }
+};
+
+void func0(std::packaged_task<double(int, char)>& p)
+{
+    std::this_thread::sleep_for(std::chrono::milliseconds(500));
+    p(3, 'a');
+}
+
+void func1(std::packaged_task<double(int, char)>& p)
+{
+    std::this_thread::sleep_for(std::chrono::milliseconds(500));
+    p(3, 'z');
+}
+
+void func2(std::packaged_task<double(int, char)>& p)
+{
+    p(3, 'a');
+    try
+    {
+        p(3, 'c');
+    }
+    catch (const std::future_error& e)
+    {
+        assert(e.code() == make_error_code(std::future_errc::promise_already_satisfied));
+    }
+}
+
+void func3(std::packaged_task<double(int, char)>& p)
+{
+    try
+    {
+        p(3, 'a');
+    }
+    catch (const std::future_error& e)
+    {
+        assert(e.code() == make_error_code(std::future_errc::no_state));
+    }
+}
+
+int main()
+{
+    {
+        std::packaged_task<double(int, char)> p(A(5));
+        std::future<double> f = p.get_future();
+        std::thread(func0, std::move(p)).detach();
+        assert(f.get() == 105.0);
+    }
+    {
+        std::packaged_task<double(int, char)> p(A(5));
+        std::future<double> f = p.get_future();
+        std::thread(func1, std::move(p)).detach();
+        try
+        {
+            f.get();
+            assert(false);
+        }
+        catch (const A& e)
+        {
+            assert(e(3, 'a') == 106);
+        }
+    }
+    {
+        std::packaged_task<double(int, char)> p(A(5));
+        std::future<double> f = p.get_future();
+        std::thread t(func2, std::move(p));
+        assert(f.get() == 105.0);
+        t.join();
+    }
+    {
+        std::packaged_task<double(int, char)> p;
+        std::thread t(func3, std::move(p));
+        t.join();
+    }
+}

Added: libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/reset.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/reset.pass.cpp?rev=112500&view=auto
==============================================================================
--- libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/reset.pass.cpp (added)
+++ libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/reset.pass.cpp Mon Aug 30 13:46:21 2010
@@ -0,0 +1,58 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <future>
+
+// class packaged_task<R(ArgTypes...)>
+
+// void reset();
+
+#include <future>
+#include <cassert>
+
+class A
+{
+    long data_;
+
+public:
+    explicit A(long i) : data_(i) {}
+
+    long operator()(long i, long j) const
+    {
+        if (j == 'z')
+            throw A(6);
+        return data_ + i + j;
+    }
+};
+
+int main()
+{
+    {
+        std::packaged_task<double(int, char)> p(A(5));
+        std::future<double> f = p.get_future();
+        p(3, 'a');
+        assert(f.get() == 105.0);
+        p.reset();
+        p(4, 'a');
+        f = p.get_future();
+        assert(f.get() == 106.0);
+    }
+    {
+        std::packaged_task<double(int, char)> p;
+        try
+        {
+            p.reset();
+            assert(false);
+        }
+        catch (const std::future_error& e)
+        {
+            assert(e.code() == make_error_code(std::future_errc::no_state));
+        }
+    }
+}

Added: libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/swap.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/swap.pass.cpp?rev=112500&view=auto
==============================================================================
--- libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/swap.pass.cpp (added)
+++ libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/swap.pass.cpp Mon Aug 30 13:46:21 2010
@@ -0,0 +1,48 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <future>
+
+// class packaged_task<R(ArgTypes...)>
+
+// void swap(packaged_task& other);
+
+#include <future>
+#include <cassert>
+
+class A
+{
+    long data_;
+
+public:
+    explicit A(long i) : data_(i) {}
+
+    long operator()(long i, long j) const {return data_ + i + j;}
+};
+
+int main()
+{
+    {
+        std::packaged_task<double(int, char)> p0(A(5));
+        std::packaged_task<double(int, char)> p;
+        p.swap(p0);
+        assert(!p0);
+        assert(p);
+        std::future<double> f = p.get_future();
+        p(3, 'a');
+        assert(f.get() == 105.0);
+    }
+    {
+        std::packaged_task<double(int, char)> p0;
+        std::packaged_task<double(int, char)> p;
+        p.swap(p0);
+        assert(!p0);
+        assert(!p);
+    }
+}

Added: libcxx/trunk/test/thread/futures/futures.tas/futures.task.nonmembers/swap.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/thread/futures/futures.tas/futures.task.nonmembers/swap.pass.cpp?rev=112500&view=auto
==============================================================================
--- libcxx/trunk/test/thread/futures/futures.tas/futures.task.nonmembers/swap.pass.cpp (added)
+++ libcxx/trunk/test/thread/futures/futures.tas/futures.task.nonmembers/swap.pass.cpp Mon Aug 30 13:46:21 2010
@@ -0,0 +1,50 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <future>
+
+// class packaged_task<R(ArgTypes...)>
+
+// template <class R, class... ArgTypes>
+//   void
+//   swap(packaged_task<R(ArgTypes...)>& x, packaged_task<R(ArgTypes...)>& y);
+
+#include <future>
+#include <cassert>
+
+class A
+{
+    long data_;
+
+public:
+    explicit A(long i) : data_(i) {}
+
+    long operator()(long i, long j) const {return data_ + i + j;}
+};
+
+int main()
+{
+    {
+        std::packaged_task<double(int, char)> p0(A(5));
+        std::packaged_task<double(int, char)> p;
+        swap(p, p0);
+        assert(!p0);
+        assert(p);
+        std::future<double> f = p.get_future();
+        p(3, 'a');
+        assert(f.get() == 105.0);
+    }
+    {
+        std::packaged_task<double(int, char)> p0;
+        std::packaged_task<double(int, char)> p;
+        swap(p, p0);
+        assert(!p0);
+        assert(!p);
+    }
+}

Added: libcxx/trunk/test/thread/futures/futures.tas/futures.task.nonmembers/uses_allocator.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/thread/futures/futures.tas/futures.task.nonmembers/uses_allocator.pass.cpp?rev=112500&view=auto
==============================================================================
--- libcxx/trunk/test/thread/futures/futures.tas/futures.task.nonmembers/uses_allocator.pass.cpp (added)
+++ libcxx/trunk/test/thread/futures/futures.tas/futures.task.nonmembers/uses_allocator.pass.cpp Mon Aug 30 13:46:21 2010
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <future>
+
+// class packaged_task<R(ArgTypes...)>
+
+// template <class Callable, class Alloc>
+//   struct uses_allocator<packaged_task<Callable>, Alloc>
+//      : true_type { };
+
+#include <future>
+#include "../../test_allocator.h"
+
+int main()
+{
+    static_assert((std::uses_allocator<std::packaged_task<double(int, char)>, test_allocator<int> >::value), "");
+}

Added: libcxx/trunk/test/thread/futures/futures.tas/types.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/thread/futures/futures.tas/types.pass.cpp?rev=112500&view=auto
==============================================================================
--- libcxx/trunk/test/thread/futures/futures.tas/types.pass.cpp (added)
+++ libcxx/trunk/test/thread/futures/futures.tas/types.pass.cpp Mon Aug 30 13:46:21 2010
@@ -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>
+
+// template<class R, class... ArgTypes>
+//     class packaged_task<R(ArgTypes...)>
+// {
+// public:
+//     typedef R result_type;
+
+#include <future>
+#include <type_traits>
+
+struct A {};
+
+int main()
+{
+    static_assert((std::is_same<std::packaged_task<A(int, char)>::result_type, A>::value), "");
+}





More information about the cfe-commits mailing list