• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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