[cfe-commits] [libcxx] r112284 - in /libcxx/trunk: include/condition_variable include/future include/thread src/future.cpp src/thread.cpp

Howard Hinnant hhinnant at apple.com
Fri Aug 27 13:10:19 PDT 2010


Author: hhinnant
Date: Fri Aug 27 15:10:19 2010
New Revision: 112284

URL: http://llvm.org/viewvc/llvm-project?rev=112284&view=rev
Log:
future continues ...

Modified:
    libcxx/trunk/include/condition_variable
    libcxx/trunk/include/future
    libcxx/trunk/include/thread
    libcxx/trunk/src/future.cpp
    libcxx/trunk/src/thread.cpp

Modified: libcxx/trunk/include/condition_variable
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/condition_variable?rev=112284&r1=112283&r2=112284&view=diff
==============================================================================
--- libcxx/trunk/include/condition_variable (original)
+++ libcxx/trunk/include/condition_variable Fri Aug 27 15:10:19 2010
@@ -61,6 +61,8 @@
     native_handle_type native_handle();
 };
 
+void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
+
 class condition_variable_any
 {
 public:

Modified: libcxx/trunk/include/future
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/future?rev=112284&r1=112283&r2=112284&view=diff
==============================================================================
--- libcxx/trunk/include/future (original)
+++ libcxx/trunk/include/future Fri Aug 27 15:10:19 2010
@@ -102,7 +102,7 @@
     void swap(promise& other);
 
     // retrieving the result
-    future<R> get_future();
+    future<R&> get_future();
 
     // setting the result
     void set_value(R& r);
@@ -130,7 +130,7 @@
     void swap(promise& other);
 
     // retrieving the result
-    future<R> get_future();
+    future<void> get_future();
 
     // setting the result
     void set_value();
@@ -441,6 +441,11 @@
 
 #include <__config>
 #include <system_error>
+#include <memory>
+#include <chrono>
+#include <exception>
+#include <__mutex_base>
+#include <thread>
 
 #pragma GCC system_header
 
@@ -523,6 +528,745 @@
     const error_code& code() const throw() {return __ec_;}
 };
 
+class __assoc_sub_state
+    : public __shared_count
+{
+protected:
+    exception_ptr __exception_;
+    mutable mutex __mut_;
+    mutable condition_variable __cv_;
+    unsigned __state_;
+
+    virtual void __on_zero_shared();
+
+public:
+    enum
+    {
+        __constructed = 1,
+        __future_attached = 2,
+        ready = 4,
+        deferred = 8
+    };
+
+    __assoc_sub_state() : __state_(0) {}
+
+    bool __has_value() const
+        {return (__state_ & __constructed) || (__exception_ != nullptr);}
+
+    void __set_future_attached() {__state_ |= __future_attached;}
+    bool __has_future_attached() const {return __state_ & __future_attached;}
+
+    void __make_ready();
+    bool __is_ready() const {return __state_ & ready;}
+
+    void set_value();
+    void set_value_at_thread_exit();
+
+    void set_exception(exception_ptr __p);
+    void set_exception_at_thread_exit(exception_ptr __p);
+
+    void copy();
+
+    void wait() const;
+    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;
+};
+
+template <class _R>
+class __assoc_state
+    : public __assoc_sub_state
+{
+    typedef __assoc_sub_state base;
+    typedef typename aligned_storage<sizeof(_R), alignment_of<_R>::value>::type _U;
+protected:
+    _U __value_;
+
+    virtual void __on_zero_shared();
+public:
+
+    template <class _Arg>
+#ifdef _LIBCPP_MOVE
+        void set_value(_Arg&& __arg);
+#else
+        void set_value(_Arg& __arg);
+#endif
+
+    template <class _Arg>
+#ifdef _LIBCPP_MOVE
+        void set_value_at_thread_exit(_Arg&& __arg);
+#else
+        void set_value_at_thread_exit(_Arg& __arg);
+#endif
+
+    _R move();
+    typename add_lvalue_reference<_R>::type copy();
+};
+
+template <class _R>
+void
+__assoc_state<_R>::__on_zero_shared()
+{
+    if (this->__state_ & base::__constructed)
+        reinterpret_cast<_R*>(&__value_)->~_R();
+    delete this;
+}
+
+template <class _R>
+template <class _Arg>
+void
+#ifdef _LIBCPP_MOVE
+__assoc_state<_R>::set_value(_Arg&& __arg)
+#else
+__assoc_state<_R>::set_value(_Arg& __arg)
+#endif
+{
+    unique_lock<mutex> __lk(this->__mut_);
+    if (this->__has_value())
+        throw future_error(make_error_code(future_errc::promise_already_satisfied));
+    ::new(&__value_) _R(_STD::forward<_Arg>(__arg));
+    this->__state_ |= base::__constructed | base::ready;
+    __lk.unlock();
+    __cv_.notify_all();
+}
+
+template <class _R>
+template <class _Arg>
+void
+#ifdef _LIBCPP_MOVE
+__assoc_state<_R>::set_value_at_thread_exit(_Arg&& __arg)
+#else
+__assoc_state<_R>::set_value_at_thread_exit(_Arg& __arg)
+#endif
+{
+    unique_lock<mutex> __lk(this->__mut_);
+    if (this->__has_value())
+        throw future_error(make_error_code(future_errc::promise_already_satisfied));
+    ::new(&__value_) _R(_STD::forward<_Arg>(__arg));
+    this->__state_ |= base::__constructed;
+    __thread_local_data->__make_ready_at_thread_exit(this);
+    __lk.unlock();
+}
+
+template <class _R>
+_R
+__assoc_state<_R>::move()
+{
+    unique_lock<mutex> __lk(this->__mut_);
+    while (!this->__is_ready())
+        this->__cv_.wait(__lk);
+    if (this->__exception_ != nullptr)
+        rethrow_exception(this->__exception_);
+    return _STD::move(*reinterpret_cast<_R*>(&__value_));
+}
+
+template <class _R>
+typename add_lvalue_reference<_R>::type
+__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 *reinterpret_cast<_R*>(&__value_);
+}
+
+template <class _R, class _Alloc>
+class __assoc_state_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()
+{
+    if (this->__state_ & base::__constructed)
+        reinterpret_cast<_R*>(&this->__value_)->~_R();
+    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
+{
+    typedef __assoc_sub_state base;
+    _Alloc __alloc_;
+
+    virtual void __on_zero_shared();
+public:
+    explicit __assoc_sub_state_alloc(const _Alloc& __a)
+        : __alloc_(__a) {}
+};
+
+template <class _Alloc>
+void
+__assoc_sub_state_alloc<_Alloc>::__on_zero_shared()
+{
+    this->~base();
+    typename _Alloc::template rebind<__assoc_state_alloc>::other __a(__alloc_);
+    this->~__assoc_sub_state_alloc();
+    __a.deallocate(this, 1);
+}
+
+template <class> class promise;
+
+// future
+
+template <class _R>
+class future
+{
+    __assoc_state<_R>* __state_;
+
+    explicit future(__assoc_state<_R>* __state);
+
+    template <class> friend class promise;
+public:
+    future() : __state_(nullptr) {}
+#ifdef _LIBCPP_MOVE
+    future(future&& __rhs)
+        : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;}
+    future(const future&) = delete;
+    future& operator=(const future&) = delete;
+    future& operator=(future&& __rhs)
+        {
+            future(std::move(__rhs)).swap(*this);
+            return *this;
+        }
+#else  // _LIBCPP_MOVE
+private:
+    future(const future&);
+    future& operator=(const future&);
+public:
+#endif  // _LIBCPP_MOVE
+    ~future();
+
+    // retrieving the value
+    _R get();
+
+    void swap(future& __rhs) {_STD::swap(__state_, __rhs.__state_);}
+
+    // functions to check state
+    bool valid() const {return __state_ != nullptr;}
+
+    void wait() const {__state_->wait();}
+    template <class _Rep, class _Period>
+        future_status
+        wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const
+            {return __state_->wait_for(__rel_time);}
+    template <class _Clock, class _Duration>
+        future_status
+        wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const
+            {return __state_->wait_until(__abs_time);}
+};
+
+template <class _R>
+future<_R>::future(__assoc_state<_R>* __state)
+    : __state_(__state)
+{
+    if (__state_->__has_future_attached())
+        throw future_error(make_error_code(future_errc::future_already_retrieved));
+    __state_->__add_shared();
+}
+
+template <class _R>
+future<_R>::~future()
+{
+    if (__state_)
+        __state_->__release_shared();
+}
+
+template <class _R>
+_R
+future<_R>::get()
+{
+    __assoc_state<_R>* __s = __state_;
+    __state_ = nullptr;
+    return __s->move();
+}
+
+template <class _R>
+class future<_R&>
+{
+    __assoc_state<_R&>* __state_;
+
+    explicit future(__assoc_state<_R&>* __state);
+
+    template <class> friend class promise;
+public:
+    future() : __state_(nullptr) {}
+#ifdef _LIBCPP_MOVE
+    future(future&& __rhs)
+        : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;}
+    future(const future&) = delete;
+    future& operator=(const future&) = delete;
+    future& operator=(future&& __rhs)
+        {
+            future(std::move(__rhs)).swap(*this);
+            return *this;
+        }
+#else  // _LIBCPP_MOVE
+private:
+    future(const future&);
+    future& operator=(const future&);
+public:
+#endif  // _LIBCPP_MOVE
+    ~future();
+
+    // retrieving the value
+    _R& get();
+
+    void swap(future& __rhs) {_STD::swap(__state_, __rhs.__state_);}
+
+    // functions to check state
+    bool valid() const {return __state_ != nullptr;}
+
+    void wait() const {__state_->wait();}
+    template <class _Rep, class _Period>
+        future_status
+        wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const
+            {return __state_->wait_for(__rel_time);}
+    template <class _Clock, class _Duration>
+        future_status
+        wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const
+            {return __state_->wait_until(__abs_time);}
+};
+
+template <class _R>
+future<_R&>::future(__assoc_state<_R&>* __state)
+    : __state_(__state)
+{
+    if (__state_->__has_future_attached())
+        throw future_error(make_error_code(future_errc::future_already_retrieved));
+    __state_->__add_shared();
+}
+
+template <class _R>
+future<_R&>::~future()
+{
+    if (__state_)
+        __state_->__release_shared();
+}
+
+template <class _R>
+_R&
+future<_R&>::get()
+{
+    __assoc_state<_R>* __s = __state_;
+    __state_ = nullptr;
+    return __s->copy();
+}
+
+template <>
+class future<void>
+{
+    __assoc_sub_state* __state_;
+
+    explicit future(__assoc_sub_state* __state);
+
+    template <class> friend class promise;
+public:
+    future() : __state_(nullptr) {}
+#ifdef _LIBCPP_MOVE
+    future(future&& __rhs)
+        : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;}
+    future(const future&) = delete;
+    future& operator=(const future&) = delete;
+    future& operator=(future&& __rhs)
+        {
+            future(std::move(__rhs)).swap(*this);
+            return *this;
+        }
+#else  // _LIBCPP_MOVE
+private:
+    future(const future&);
+    future& operator=(const future&);
+public:
+#endif  // _LIBCPP_MOVE
+    ~future();
+
+    // retrieving the value
+    void get();
+
+    void swap(future& __rhs) {_STD::swap(__state_, __rhs.__state_);}
+
+    // functions to check state
+    bool valid() const {return __state_ != nullptr;}
+
+    void wait() const {__state_->wait();}
+    template <class _Rep, class _Period>
+        future_status
+        wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const
+            {return __state_->wait_for(__rel_time);}
+    template <class _Clock, class _Duration>
+        future_status
+        wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const
+            {return __state_->wait_until(__abs_time);}
+};
+
+// promise<R>
+
+template <class _R>
+class promise
+{
+    __assoc_state<_R>* __state_;
+public:
+    promise();
+    template <class _Alloc>
+        promise(allocator_arg_t, const _Alloc& __a);
+#ifdef _LIBCPP_MOVE
+    promise(promise&& __rhs)
+        : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;}
+    promise(const promise& __rhs) = delete;
+#else  // _LIBCPP_MOVE
+private:
+    promise(const promise& __rhs);
+public:
+#endif  // _LIBCPP_MOVE
+    ~promise();
+
+    // assignment
+#ifdef _LIBCPP_MOVE
+    promise& operator=(promise&& __rhs)
+        {
+            promise(std::move(__rhs)).swap(*this);
+            return *this;
+        }
+    promise& operator=(const promise& __rhs) = delete;
+#else  // _LIBCPP_MOVE
+private:
+    promise& operator=(const promise& __rhs);
+public:
+#endif  // _LIBCPP_MOVE
+    void swap(promise& __rhs) {_STD::swap(__state_, __rhs.__state_);}
+
+    // retrieving the result
+    future<_R> get_future();
+
+    // setting the result
+    void set_value(const _R& __r);
+#ifdef _LIBCPP_MOVE
+    void set_value(_R&& __r);
+#endif
+    void set_exception(exception_ptr __p);
+
+    // setting the result with deferred notification
+    void set_value_at_thread_exit(const _R& __r);
+#ifdef _LIBCPP_MOVE
+    void set_value_at_thread_exit(_R&& __r);
+#endif
+    void set_exception_at_thread_exit(exception_ptr __p);
+};
+
+template <class _R>
+promise<_R>::promise()
+    : __state_(new __assoc_state<_R>)
+{
+}
+
+template <class _R>
+template <class _Alloc>
+promise<_R>::promise(allocator_arg_t, const _Alloc& __a0)
+{
+    typedef typename _Alloc::template rebind<__assoc_state_alloc<_R, _Alloc> >::other _A2;
+    typedef __allocator_destructor<_A2> _D2;
+    _A2 __a(__a0);
+    unique_ptr<__assoc_state_alloc<_R, _Alloc>, _D2> __hold(__a.allocate(1), _D2(__a, 1));
+    ::new(__hold.get()) __assoc_state_alloc<_R, _Alloc>(__a0);
+    __state_ = __hold.release();
+}
+
+template <class _R>
+promise<_R>::~promise()
+{
+    if (__state_)
+    {
+        if (!__state_->__has_value() && __state_->use_count() > 1)
+            __state_->set_exception(make_exception_ptr(
+                      future_error(make_error_code(future_errc::broken_promise))
+                                                      ));
+        __state_->__release_shared();
+    }
+}
+
+template <class _R>
+future<_R>
+promise<_R>::get_future()
+{
+    if (__state_ == nullptr)
+        throw future_error(make_error_code(future_errc::no_state));
+    return future<_R>(__state_);
+}
+
+template <class _R>
+void
+promise<_R>::set_value(const _R& __r)
+{
+    if (__state_ == nullptr)
+        throw future_error(make_error_code(future_errc::no_state));
+    __state_->set_value(__r);
+}
+
+#ifdef _LIBCPP_MOVE
+
+template <class _R>
+void
+promise<_R>::set_value(_R&& __r)
+{
+    if (__state_ == nullptr)
+        throw future_error(make_error_code(future_errc::no_state));
+    __state_->set_value(_STD::move(__r));
+}
+
+#endif  // _LIBCPP_MOVE
+
+template <class _R>
+void
+promise<_R>::set_exception(exception_ptr __p)
+{
+    if (__state_ == nullptr)
+        throw future_error(make_error_code(future_errc::no_state));
+    __state_->set_exception(__p);
+}
+
+template <class _R>
+void
+promise<_R>::set_value_at_thread_exit(const _R& __r)
+{
+    if (__state_ == nullptr)
+        throw future_error(make_error_code(future_errc::no_state));
+    __state_->set_value_at_thread_exit(__r);
+}
+
+#ifdef _LIBCPP_MOVE
+
+template <class _R>
+void
+promise<_R>::set_value_at_thread_exit(_R&& __r)
+{
+    if (__state_ == nullptr)
+        throw future_error(make_error_code(future_errc::no_state));
+    __state_->set_value_at_thread_exit(_STD::move(__r));
+}
+
+#endif  // _LIBCPP_MOVE
+
+template <class _R>
+void
+promise<_R>::set_exception_at_thread_exit(exception_ptr __p)
+{
+    if (__state_ == nullptr)
+        throw future_error(make_error_code(future_errc::no_state));
+    __state_->set_exception_at_thread_exit(__p);
+}
+
+// promise<R&>
+
+template <class _R>
+class promise<_R&>
+{
+    __assoc_state<_R&>* __state_;
+public:
+    promise();
+    template <class _Allocator>
+        promise(allocator_arg_t, const _Allocator& __a);
+#ifdef _LIBCPP_MOVE
+    promise(promise&& __rhs)
+        : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;}
+    promise(const promise& __rhs) = delete;
+#else  // _LIBCPP_MOVE
+private:
+    promise(const promise& __rhs);
+public:
+#endif  // _LIBCPP_MOVE
+    ~promise();
+
+    // assignment
+#ifdef _LIBCPP_MOVE
+    promise& operator=(promise&& __rhs)
+        {
+            promise(std::move(__rhs)).swap(*this);
+            return *this;
+        }
+    promise& operator=(const promise& __rhs) = delete;
+#else  // _LIBCPP_MOVE
+private:
+    promise& operator=(const promise& __rhs);
+public:
+#endif  // _LIBCPP_MOVE
+    void swap(promise& __rhs) {_STD::swap(__state_, __rhs.__state_);}
+
+    // retrieving the result
+    future<_R&> get_future();
+
+    // setting the result
+    void set_value(_R& __r);
+    void set_exception(exception_ptr __p);
+
+    // setting the result with deferred notification
+    void set_value_at_thread_exit(_R&);
+    void set_exception_at_thread_exit(exception_ptr __p);
+};
+
+template <class _R>
+promise<_R&>::promise()
+    : __state_(new __assoc_state<_R&>)
+{
+}
+
+template <class _R>
+template <class _Alloc>
+promise<_R&>::promise(allocator_arg_t, const _Alloc& __a0)
+{
+    typedef typename _Alloc::template rebind<__assoc_state_alloc<_R&, _Alloc> >::other _A2;
+    typedef __allocator_destructor<_A2> _D2;
+    _A2 __a(__a0);
+    unique_ptr<__assoc_state_alloc<_R&, _Alloc>, _D2> __hold(__a.allocate(1), _D2(__a, 1));
+    ::new(__hold.get()) __assoc_state_alloc<_R&, _Alloc>(__a0);
+    __state_ = __hold.release();
+}
+
+template <class _R>
+promise<_R&>::~promise()
+{
+    if (__state_)
+    {
+        if (!__state_->__has_value() && __state_->use_count() > 1)
+            __state_->set_exception(make_exception_ptr(
+                      future_error(make_error_code(future_errc::broken_promise))
+                                                      ));
+        __state_->__release_shared();
+    }
+}
+
+template <class _R>
+future<_R&>
+promise<_R&>::get_future()
+{
+    if (__state_ == nullptr)
+        throw future_error(make_error_code(future_errc::no_state));
+    return future<_R&>(__state_);
+}
+
+template <class _R>
+void
+promise<_R&>::set_value(_R& __r)
+{
+    if (__state_ == nullptr)
+        throw future_error(make_error_code(future_errc::no_state));
+    __state_->set_value(__r);
+}
+
+template <class _R>
+void
+promise<_R&>::set_exception(exception_ptr __p)
+{
+    if (__state_ == nullptr)
+        throw future_error(make_error_code(future_errc::no_state));
+    __state_->set_exception(__p);
+}
+
+template <class _R>
+void
+promise<_R&>::set_value_at_thread_exit(_R& __r)
+{
+    if (__state_ == nullptr)
+        throw future_error(make_error_code(future_errc::no_state));
+    __state_->set_value_at_thread_exit(__r);
+}
+
+template <class _R>
+void
+promise<_R&>::set_exception_at_thread_exit(exception_ptr __p)
+{
+    if (__state_ == nullptr)
+        throw future_error(make_error_code(future_errc::no_state));
+    __state_->set_exception_at_thread_exit(__p);
+}
+
+// promise<void>
+
+template <>
+class promise<void>
+{
+    __assoc_sub_state* __state_;
+public:
+    promise();
+    template <class _Allocator>
+        promise(allocator_arg_t, const _Allocator& __a);
+#ifdef _LIBCPP_MOVE
+    promise(promise&& __rhs)
+        : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;}
+    promise(const promise& __rhs) = delete;
+#else  // _LIBCPP_MOVE
+private:
+    promise(const promise& __rhs);
+public:
+#endif  // _LIBCPP_MOVE
+    ~promise();
+
+    // assignment
+#ifdef _LIBCPP_MOVE
+    promise& operator=(promise&& __rhs)
+        {
+            promise(std::move(__rhs)).swap(*this);
+            return *this;
+        }
+    promise& operator=(const promise& __rhs) = delete;
+#else  // _LIBCPP_MOVE
+private:
+    promise& operator=(const promise& __rhs);
+public:
+#endif  // _LIBCPP_MOVE
+    void swap(promise& __rhs) {_STD::swap(__state_, __rhs.__state_);}
+
+    // retrieving the result
+    future<void> get_future();
+
+    // setting the result
+    void set_value();
+    void set_exception(exception_ptr __p);
+
+    // setting the result with deferred notification
+    void set_value_at_thread_exit();
+    void set_exception_at_thread_exit(exception_ptr __p);
+};
+
+template <class _Alloc>
+promise<void>::promise(allocator_arg_t, const _Alloc& __a0)
+{
+    typedef typename _Alloc::template rebind<__assoc_sub_state_alloc<_Alloc> >::other _A2;
+    typedef __allocator_destructor<_A2> _D2;
+    _A2 __a(__a0);
+    unique_ptr<__assoc_sub_state_alloc<_Alloc>, _D2> __hold(__a.allocate(1), _D2(__a, 1));
+    ::new(__hold.get()) __assoc_sub_state_alloc<_Alloc>(__a0);
+    __state_ = __hold.release();
+}
+
+template <class _R>
+inline _LIBCPP_INLINE_VISIBILITY
+void
+swap(promise<_R>& __x, promise<_R>& __y)
+{
+    __x.swap(__y);
+}
+
+template <class _R, class _Alloc>
+    struct uses_allocator<promise<_R>, _Alloc> : public true_type {};
+
 _LIBCPP_END_NAMESPACE_STD
 
 #endif  // _LIBCPP_FUTURE

Modified: libcxx/trunk/include/thread
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/thread?rev=112284&r1=112283&r2=112284&view=diff
==============================================================================
--- libcxx/trunk/include/thread (original)
+++ libcxx/trunk/include/thread Fri Aug 27 15:10:19 2010
@@ -103,6 +103,68 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
+template <class _Tp>
+class __thread_specific_ptr
+{
+    pthread_key_t __key_;
+
+    __thread_specific_ptr(const __thread_specific_ptr&);
+    __thread_specific_ptr& operator=(const __thread_specific_ptr&);
+
+    static void __at_thread_exit(void*);
+public:
+    typedef _Tp* pointer;
+
+    __thread_specific_ptr();
+    ~__thread_specific_ptr();
+
+    pointer get() const {return static_cast<_Tp*>(pthread_getspecific(__key_));}
+    pointer operator*() const {return *get();}
+    pointer operator->() const {return get();}
+    pointer release();
+    void reset(pointer __p = nullptr);
+};
+
+template <class _Tp>
+void
+__thread_specific_ptr<_Tp>::__at_thread_exit(void* __p)
+{
+	delete static_cast<pointer>(__p);
+}
+
+template <class _Tp>
+__thread_specific_ptr<_Tp>::__thread_specific_ptr()
+{
+    int __ec = pthread_key_create(&__key_, &__thread_specific_ptr::__at_thread_exit);
+	if (__ec)
+		throw system_error(error_code(__ec, system_category()),
+		                   "__thread_specific_ptr construction failed");
+}
+
+template <class _Tp>
+__thread_specific_ptr<_Tp>::~__thread_specific_ptr()
+{
+	pthread_key_delete(__key_);
+}
+
+template <class _Tp>
+typename __thread_specific_ptr<_Tp>::pointer
+__thread_specific_ptr<_Tp>::release()
+{
+	pointer __p = get();
+	pthread_setspecific(__key_, 0);
+	return __p;
+}
+
+template <class _Tp>
+void
+__thread_specific_ptr<_Tp>::reset(pointer __p)
+{
+	pointer __p_old = get();
+	pthread_setspecific(__key_, __p);
+	delete __p_old;
+}
+
 class thread;
 class __thread_id;
 
@@ -219,10 +281,30 @@
     static unsigned hardware_concurrency();
 };
 
+class __assoc_sub_state;
+
+class __thread_struct_imp;
+
+class __thread_struct
+{
+    __thread_struct_imp* __p_;
+
+    __thread_struct(const __thread_struct&);
+    __thread_struct& operator=(const __thread_struct&);
+public:
+    __thread_struct();
+    ~__thread_struct();
+
+    void __make_ready_at_thread_exit(__assoc_sub_state*);
+};
+
+extern __thread_specific_ptr<__thread_struct> __thread_local_data;
+
 template <class _F>
 void*
 __thread_proxy(void* __vp)
 {
+    __thread_local_data.reset(new __thread_struct);
     std::unique_ptr<_F> __p(static_cast<_F*>(__vp));
     (*__p)();
     return nullptr;

Modified: libcxx/trunk/src/future.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/src/future.cpp?rev=112284&r1=112283&r2=112284&view=diff
==============================================================================
--- libcxx/trunk/src/future.cpp (original)
+++ libcxx/trunk/src/future.cpp Fri Aug 27 15:10:19 2010
@@ -60,4 +60,161 @@
 {
 }
 
+void
+__assoc_sub_state::__on_zero_shared()
+{
+    delete this;
+}
+
+void
+__assoc_sub_state::set_value()
+{
+    unique_lock<mutex> __lk(__mut_);
+    if (__has_value())
+        throw future_error(make_error_code(future_errc::promise_already_satisfied));
+    __state_ |= __constructed | ready;
+    __lk.unlock();
+    __cv_.notify_all();
+}
+
+void
+__assoc_sub_state::set_value_at_thread_exit()
+{
+    unique_lock<mutex> __lk(__mut_);
+    if (__has_value())
+        throw future_error(make_error_code(future_errc::promise_already_satisfied));
+    __state_ |= __constructed;
+    __thread_local_data->__make_ready_at_thread_exit(this);
+    __lk.unlock();
+}
+
+void
+__assoc_sub_state::set_exception(exception_ptr __p)
+{
+    unique_lock<mutex> __lk(__mut_);
+    if (__has_value())
+        throw future_error(make_error_code(future_errc::promise_already_satisfied));
+    __exception_ = __p;
+    __state_ |= ready;
+    __lk.unlock();
+    __cv_.notify_all();
+}
+
+void
+__assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p)
+{
+    unique_lock<mutex> __lk(__mut_);
+    if (__has_value())
+        throw future_error(make_error_code(future_errc::promise_already_satisfied));
+    __exception_ = __p;
+    __thread_local_data->__make_ready_at_thread_exit(this);
+    __lk.unlock();
+}
+
+void
+__assoc_sub_state::__make_ready()
+{
+    unique_lock<mutex> __lk(__mut_);
+    __state_ |= ready;
+    __lk.unlock();
+    __cv_.notify_all();
+}
+
+void
+__assoc_sub_state::copy()
+{
+    unique_lock<mutex> __lk(__mut_);
+    while (!__is_ready())
+        __cv_.wait(__lk);
+    if (__exception_ != nullptr)
+        rethrow_exception(__exception_);
+}
+
+void
+__assoc_sub_state::wait() const
+{
+    unique_lock<mutex> __lk(__mut_);
+    while (!__is_ready())
+        __cv_.wait(__lk);
+}
+
+future<void>::future(__assoc_sub_state* __state)
+    : __state_(__state)
+{
+    if (__state_->__has_future_attached())
+        throw future_error(make_error_code(future_errc::future_already_retrieved));
+    __state_->__add_shared();
+}
+
+future<void>::~future()
+{
+    if (__state_)
+        __state_->__release_shared();
+}
+
+void
+future<void>::get()
+{
+    __assoc_sub_state* __s = __state_;
+    __state_ = nullptr;
+    return __s->copy();
+}
+
+promise<void>::promise()
+    : __state_(new __assoc_sub_state)
+{
+}
+
+promise<void>::~promise()
+{
+    if (__state_)
+    {
+        if (!__state_->__has_value() && __state_->use_count() > 1)
+            __state_->set_exception(make_exception_ptr(
+                      future_error(make_error_code(future_errc::broken_promise))
+                                                      ));
+        __state_->__release_shared();
+    }
+}
+
+future<void>
+promise<void>::get_future()
+{
+    if (__state_ == nullptr)
+        throw future_error(make_error_code(future_errc::no_state));
+    return future<void>(__state_);
+}
+
+void
+promise<void>::set_value()
+{
+    if (__state_ == nullptr)
+        throw future_error(make_error_code(future_errc::no_state));
+    __state_->set_value();
+}
+
+void
+promise<void>::set_exception(exception_ptr __p)
+{
+    if (__state_ == nullptr)
+        throw future_error(make_error_code(future_errc::no_state));
+    __state_->set_exception(__p);
+}
+
+void
+promise<void>::set_value_at_thread_exit()
+{
+    if (__state_ == nullptr)
+        throw future_error(make_error_code(future_errc::no_state));
+    __state_->set_value_at_thread_exit();
+}
+
+void
+promise<void>::set_exception_at_thread_exit(exception_ptr __p)
+{
+    if (__state_ == nullptr)
+        throw future_error(make_error_code(future_errc::no_state));
+    __state_->set_exception_at_thread_exit(__p);
+}
+
 _LIBCPP_END_NAMESPACE_STD

Modified: libcxx/trunk/src/thread.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/src/thread.cpp?rev=112284&r1=112283&r2=112284&view=diff
==============================================================================
--- libcxx/trunk/src/thread.cpp (original)
+++ libcxx/trunk/src/thread.cpp Fri Aug 27 15:10:19 2010
@@ -9,6 +9,8 @@
 
 #include "thread"
 #include "exception"
+#include "vector"
+#include "future"
 #include <sys/types.h>
 #include <sys/sysctl.h>
 
@@ -81,4 +83,57 @@
 
 }  // this_thread
 
+__thread_specific_ptr<__thread_struct> __thread_local_data;
+
+// __thread_struct_imp
+
+class __thread_struct_imp
+{
+    typedef vector<__assoc_sub_state*> _AsyncStates;
+    _AsyncStates async_states_;
+
+    __thread_struct_imp(const __thread_struct_imp&);
+    __thread_struct_imp& operator=(const __thread_struct_imp&);
+public:
+    __thread_struct_imp() {}
+    ~__thread_struct_imp();
+
+    void __make_ready_at_thread_exit(__assoc_sub_state* __s);
+};
+
+__thread_struct_imp::~__thread_struct_imp()
+{
+    for (_AsyncStates::iterator i = async_states_.begin(), e = async_states_.end();
+            i != e; ++i)
+    {
+        (*i)->__make_ready();
+        (*i)->__release_shared();
+    }
+}
+
+void
+__thread_struct_imp::__make_ready_at_thread_exit(__assoc_sub_state* __s)
+{
+    async_states_.push_back(__s);
+    __s->__add_shared();
+}
+
+// __thread_struct
+
+__thread_struct::__thread_struct()
+    : __p_(new __thread_struct_imp)
+{
+}
+
+__thread_struct::~__thread_struct()
+{
+    delete __p_;
+}
+
+void
+__thread_struct::__make_ready_at_thread_exit(__assoc_sub_state* __s)
+{
+    __p_->__make_ready_at_thread_exit(__s);
+}
+
 _LIBCPP_END_NAMESPACE_STD





More information about the cfe-commits mailing list