[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