Last active
August 29, 2015 14:03
-
-
Save hengyunabc/d48fbebdb9bddcdf05e9 to your computer and use it in GitHub Desktop.
std::notify_all_at_thread_exit, llvm libc++ implements.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template <class _Fp> | |
void* | |
__thread_proxy(void* __vp) | |
{ | |
__thread_local_data().reset(new __thread_struct); | |
std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); | |
(*__p)(); | |
return nullptr; | |
} | |
template <class _Fp> | |
thread::thread(_Fp __f) | |
{ | |
std::unique_ptr<_Fp> __p(new _Fp(__f)); | |
int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Fp>, __p.get()); | |
if (__ec == 0) | |
__p.release(); | |
else | |
__throw_system_error(__ec, "thread constructor failed"); | |
} | |
class __thread_specific_ptr | |
{ | |
pthread_key_t __key_; | |
} | |
template <class _Tp> | |
__thread_specific_ptr<_Tp>::__thread_specific_ptr() | |
{ | |
int __ec = pthread_key_create(&__key_, &__thread_specific_ptr::__at_thread_exit); | |
} | |
template <class _Tp> | |
void | |
__thread_specific_ptr<_Tp>::__at_thread_exit(void* __p) | |
{ | |
delete static_cast<pointer>(__p); | |
} | |
template <class _Tp> | |
void | |
__thread_specific_ptr<_Tp>::reset(pointer __p) | |
{ | |
pointer __p_old = get(); | |
pthread_setspecific(__key_, __p); | |
delete __p_old; | |
} | |
class _LIBCPP_TYPE_VIS __thread_struct | |
{ | |
__thread_struct_imp* __p_; | |
__thread_struct(const __thread_struct&); | |
__thread_struct& operator=(const __thread_struct&); | |
public: | |
__thread_struct(); | |
~__thread_struct(); | |
void notify_all_at_thread_exit(condition_variable*, mutex*); | |
void __make_ready_at_thread_exit(__assoc_sub_state*); | |
}; | |
__thread_specific_ptr<__thread_struct>& | |
__thread_local_data() | |
{ | |
static __thread_specific_ptr<__thread_struct> __p; | |
return __p; | |
} | |
class _LIBCPP_HIDDEN __thread_struct_imp | |
{ | |
typedef vector<__assoc_sub_state*, | |
__hidden_allocator<__assoc_sub_state*> > _AsyncStates; | |
typedef vector<pair<condition_variable*, mutex*>, | |
__hidden_allocator<pair<condition_variable*, mutex*> > > _Notify; | |
_AsyncStates async_states_; | |
_Notify notify_; | |
__thread_struct_imp(const __thread_struct_imp&); | |
__thread_struct_imp& operator=(const __thread_struct_imp&); | |
public: | |
__thread_struct_imp() {} | |
~__thread_struct_imp(); | |
void notify_all_at_thread_exit(condition_variable* cv, mutex* m); | |
void __make_ready_at_thread_exit(__assoc_sub_state* __s); | |
}; | |
__thread_struct_imp::~__thread_struct_imp() | |
{ | |
for (_Notify::iterator i = notify_.begin(), e = notify_.end(); | |
i != e; ++i) | |
{ | |
i->second->unlock(); | |
i->first->notify_all(); | |
} | |
for (_AsyncStates::iterator i = async_states_.begin(), e = async_states_.end(); | |
i != e; ++i) | |
{ | |
(*i)->__make_ready(); | |
(*i)->__release_shared(); | |
} | |
} | |
void | |
__thread_struct_imp::notify_all_at_thread_exit(condition_variable* cv, mutex* m) | |
{ | |
notify_.push_back(pair<condition_variable*, mutex*>(cv, m)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment