]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | |
7c673cae FG |
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 | { | |
33 | static void delete_epoch_tss_data(void* data) | |
34 | { | |
35 | free(data); | |
36 | } | |
37 | ||
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 | { | |
48 | delete_epoch_tss_key_on_dlclose_t() | |
49 | { | |
50 | } | |
51 | ~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 | ||
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 // |