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::__anon1529684c0111::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::__anon1529684c0111::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