1 // Copyright (C) 2007 Anthony Williams 2 // 3 // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 6 #include <boost/thread/detail/config.hpp> 7 #ifdef BOOST_THREAD_ONCE_ATOMIC 8 #include "./once_atomic.cpp" 9 #else 10 #define __STDC_CONSTANT_MACROS 11 #include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp> 12 #include <boost/thread/once.hpp> 13 #include <boost/assert.hpp> 14 #include <boost/throw_exception.hpp> 15 #include <pthread.h> 16 #include <stdlib.h> 17 #include <memory> 18 19 namespace boost 20 { 21 namespace thread_detail 22 { 23 BOOST_THREAD_DECL uintmax_atomic_t once_global_epoch=BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C; 24 BOOST_THREAD_DECL pthread_mutex_t once_epoch_mutex=PTHREAD_MUTEX_INITIALIZER; 25 BOOST_THREAD_DECL pthread_cond_t once_epoch_cv = PTHREAD_COND_INITIALIZER; 26 27 namespace 28 { 29 pthread_key_t epoch_tss_key; 30 pthread_once_t epoch_tss_key_flag=PTHREAD_ONCE_INIT; 31 32 extern "C" 33 { delete_epoch_tss_data(void * data)34 static void delete_epoch_tss_data(void* data) 35 { 36 free(data); 37 } 38 create_epoch_tss_key()39 static void create_epoch_tss_key() 40 { 41 BOOST_VERIFY(!pthread_key_create(&epoch_tss_key,delete_epoch_tss_data)); 42 } 43 } 44 45 #if defined BOOST_THREAD_PATCH 46 const pthread_once_t pthread_once_init_value=PTHREAD_ONCE_INIT; 47 struct BOOST_THREAD_DECL delete_epoch_tss_key_on_dlclose_t 48 { delete_epoch_tss_key_on_dlclose_tboost::thread_detail::__anon097e33f60111::delete_epoch_tss_key_on_dlclose_t49 delete_epoch_tss_key_on_dlclose_t() 50 { 51 } ~delete_epoch_tss_key_on_dlclose_tboost::thread_detail::__anon097e33f60111::delete_epoch_tss_key_on_dlclose_t52 ~delete_epoch_tss_key_on_dlclose_t() 53 { 54 if(memcmp(&epoch_tss_key_flag, &pthread_once_init_value, sizeof(pthread_once_t))) 55 { 56 pthread_key_delete(epoch_tss_key); 57 } 58 } 59 }; 60 delete_epoch_tss_key_on_dlclose_t delete_epoch_tss_key_on_dlclose; 61 #endif 62 } 63 get_once_per_thread_epoch()64 uintmax_atomic_t& get_once_per_thread_epoch() 65 { 66 BOOST_VERIFY(!pthread_once(&epoch_tss_key_flag,create_epoch_tss_key)); 67 void* data=pthread_getspecific(epoch_tss_key); 68 if(!data) 69 { 70 data=malloc(sizeof(thread_detail::uintmax_atomic_t)); 71 if(!data) BOOST_THROW_EXCEPTION(std::bad_alloc()); 72 BOOST_VERIFY(!pthread_setspecific(epoch_tss_key,data)); 73 *static_cast<thread_detail::uintmax_atomic_t*>(data)=BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C; 74 } 75 return *static_cast<thread_detail::uintmax_atomic_t*>(data); 76 } 77 } 78 79 } 80 #endif // 81