1 | #ifndef BOOST_THREAD_TSS_HPP |
2 | #define BOOST_THREAD_TSS_HPP |
3 | // Distributed under the Boost Software License, Version 1.0. (See |
4 | // accompanying file LICENSE_1_0.txt or copy at |
5 | // http://www.boost.org/LICENSE_1_0.txt) |
6 | // (C) Copyright 2007-8 Anthony Williams |
7 | |
8 | #include <boost/thread/detail/config.hpp> |
9 | #include <boost/shared_ptr.hpp> |
10 | #include <boost/thread/detail/thread_heap_alloc.hpp> |
11 | |
12 | #include <boost/config/abi_prefix.hpp> |
13 | |
14 | namespace boost |
15 | { |
16 | namespace detail |
17 | { |
18 | struct tss_cleanup_function |
19 | { |
20 | virtual ~tss_cleanup_function() |
21 | {} |
22 | |
23 | virtual void operator()(void* data)=0; |
24 | }; |
25 | |
26 | BOOST_THREAD_DECL void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing); |
27 | BOOST_THREAD_DECL void* get_tss_data(void const* key); |
28 | } |
29 | |
30 | template <typename T> |
31 | class thread_specific_ptr |
32 | { |
33 | private: |
34 | thread_specific_ptr(thread_specific_ptr&); |
35 | thread_specific_ptr& operator=(thread_specific_ptr&); |
36 | |
37 | struct delete_data: |
38 | detail::tss_cleanup_function |
39 | { |
40 | void operator()(void* data) |
41 | { |
42 | delete static_cast<T*>(data); |
43 | } |
44 | }; |
45 | |
46 | struct run_custom_cleanup_function: |
47 | detail::tss_cleanup_function |
48 | { |
49 | void (*cleanup_function)(T*); |
50 | |
51 | explicit run_custom_cleanup_function(void (*cleanup_function_)(T*)): |
52 | cleanup_function(cleanup_function_) |
53 | {} |
54 | |
55 | void operator()(void* data) |
56 | { |
57 | cleanup_function(static_cast<T*>(data)); |
58 | } |
59 | }; |
60 | |
61 | |
62 | boost::shared_ptr<detail::tss_cleanup_function> cleanup; |
63 | |
64 | public: |
65 | typedef T element_type; |
66 | |
67 | thread_specific_ptr(): |
68 | cleanup(detail::heap_new<delete_data>(),detail::do_heap_delete<delete_data>()) |
69 | {} |
70 | explicit thread_specific_ptr(void (*func_)(T*)) |
71 | { |
72 | if(func_) |
73 | { |
74 | cleanup.reset(detail::heap_new<run_custom_cleanup_function>(func_),detail::do_heap_delete<run_custom_cleanup_function>()); |
75 | } |
76 | } |
77 | ~thread_specific_ptr() |
78 | { |
79 | detail::set_tss_data(this,boost::shared_ptr<detail::tss_cleanup_function>(),0,true); |
80 | } |
81 | |
82 | T* get() const |
83 | { |
84 | return static_cast<T*>(detail::get_tss_data(this)); |
85 | } |
86 | T* operator->() const |
87 | { |
88 | return get(); |
89 | } |
90 | typename boost::detail::sp_dereference< T >::type operator*() const |
91 | { |
92 | return *get(); |
93 | } |
94 | T* release() |
95 | { |
96 | T* const temp=get(); |
97 | detail::set_tss_data(this,boost::shared_ptr<detail::tss_cleanup_function>(),0,false); |
98 | return temp; |
99 | } |
100 | void reset(T* new_value=0) |
101 | { |
102 | T* const current_value=get(); |
103 | if(current_value!=new_value) |
104 | { |
105 | detail::set_tss_data(this,cleanup,new_value,true); |
106 | } |
107 | } |
108 | }; |
109 | } |
110 | |
111 | #include <boost/config/abi_suffix.hpp> |
112 | |
113 | #endif |
114 | |