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/once.hpp> 12 #include <boost/assert.hpp> 13 #include <boost/throw_exception.hpp> 14 #include <pthread.h> 15 #include <stdlib.h> 16 #include <memory> 17 #include <string.h> // memcmp. 18 namespace boost 19 { 20 namespace thread_detail 21 { 22 BOOST_THREAD_DECL uintmax_atomic_t once_global_epoch=BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C; 23 BOOST_THREAD_DECL pthread_mutex_t once_epoch_mutex=PTHREAD_MUTEX_INITIALIZER; 24 BOOST_THREAD_DECL pthread_cond_t once_epoch_cv = PTHREAD_COND_INITIALIZER; 25 26 namespace 27 { 28 pthread_key_t epoch_tss_key; 29 pthread_once_t epoch_tss_key_flag=PTHREAD_ONCE_INIT; 30 31 extern "C" 32 { delete_epoch_tss_data(void * data)33 static void delete_epoch_tss_data(void* data) 34 { 35 free(data); 36 } 37 create_epoch_tss_key()38 static void create_epoch_tss_key() 39 { 40 BOOST_VERIFY(!pthread_key_create(&epoch_tss_key,delete_epoch_tss_data)); 41 } 42 } 43 44 #if defined BOOST_THREAD_PATCH 45 const pthread_once_t pthread_once_init_value=PTHREAD_ONCE_INIT; 46 struct BOOST_THREAD_DECL delete_epoch_tss_key_on_dlclose_t 47 { delete_epoch_tss_key_on_dlclose_tboost::thread_detail::__anonc0bda87e0111::delete_epoch_tss_key_on_dlclose_t48 delete_epoch_tss_key_on_dlclose_t() 49 { 50 } ~delete_epoch_tss_key_on_dlclose_tboost::thread_detail::__anonc0bda87e0111::delete_epoch_tss_key_on_dlclose_t51 ~delete_epoch_tss_key_on_dlclose_t() 52 { 53 if(memcmp(&epoch_tss_key_flag, &pthread_once_init_value, sizeof(pthread_once_t))) 54 { 55 void* data = pthread_getspecific(epoch_tss_key); 56 if (data) 57 delete_epoch_tss_data(data); 58 pthread_key_delete(epoch_tss_key); 59 } 60 } 61 }; 62 delete_epoch_tss_key_on_dlclose_t delete_epoch_tss_key_on_dlclose; 63 #endif 64 } 65 get_once_per_thread_epoch()66 uintmax_atomic_t& get_once_per_thread_epoch() 67 { 68 BOOST_VERIFY(!pthread_once(&epoch_tss_key_flag,create_epoch_tss_key)); 69 void* data=pthread_getspecific(epoch_tss_key); 70 if(!data) 71 { 72 data=malloc(sizeof(thread_detail::uintmax_atomic_t)); 73 if(!data) BOOST_THROW_EXCEPTION(std::bad_alloc()); 74 BOOST_VERIFY(!pthread_setspecific(epoch_tss_key,data)); 75 *static_cast<thread_detail::uintmax_atomic_t*>(data)=BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C; 76 } 77 return *static_cast<thread_detail::uintmax_atomic_t*>(data); 78 } 79 } 80 81 } 82 #endif // 83