1 | /* |
---|---|
2 | * Copyright Andrey Semashev 2007 - 2015. |
3 | * Distributed under the Boost Software License, Version 1.0. |
4 | * (See accompanying file LICENSE_1_0.txt or copy at |
5 | * http://www.boost.org/LICENSE_1_0.txt) |
6 | */ |
7 | /*! |
8 | * \file thread_specific.hpp |
9 | * \author Andrey Semashev |
10 | * \date 01.03.2008 |
11 | * |
12 | * \brief This header is the Boost.Log library implementation, see the library documentation |
13 | * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. |
14 | */ |
15 | |
16 | #ifndef BOOST_LOG_DETAIL_THREAD_SPECIFIC_HPP_INCLUDED_ |
17 | #define BOOST_LOG_DETAIL_THREAD_SPECIFIC_HPP_INCLUDED_ |
18 | |
19 | #include <boost/type_traits/is_pod.hpp> |
20 | #include <boost/log/detail/config.hpp> |
21 | |
22 | #ifdef BOOST_HAS_PRAGMA_ONCE |
23 | #pragma once |
24 | #endif |
25 | |
26 | #if !defined(BOOST_LOG_NO_THREADS) |
27 | |
28 | #include <boost/log/detail/header.hpp> |
29 | |
30 | namespace boost { |
31 | |
32 | BOOST_LOG_OPEN_NAMESPACE |
33 | |
34 | namespace aux { |
35 | |
36 | //! Base class for TLS to hide platform-specific storage management |
37 | class thread_specific_base |
38 | { |
39 | private: |
40 | #if defined(BOOST_THREAD_PLATFORM_WIN32) |
41 | typedef unsigned long key_storage; |
42 | #else |
43 | typedef void* key_storage; |
44 | #endif |
45 | |
46 | key_storage m_Key; |
47 | |
48 | protected: |
49 | BOOST_LOG_API thread_specific_base(); |
50 | BOOST_LOG_API ~thread_specific_base(); |
51 | BOOST_LOG_API void* get_content() const; |
52 | BOOST_LOG_API void set_content(void* value) const; |
53 | |
54 | // Copying prohibited |
55 | BOOST_DELETED_FUNCTION(thread_specific_base(thread_specific_base const&)) |
56 | BOOST_DELETED_FUNCTION(thread_specific_base& operator= (thread_specific_base const&)) |
57 | }; |
58 | |
59 | //! A TLS wrapper for small POD types with least possible overhead |
60 | template< typename T > |
61 | class thread_specific : |
62 | public thread_specific_base |
63 | { |
64 | static_assert(sizeof(T) <= sizeof(void*) && is_pod< T >::value, "Boost.Log: Thread-specific values must be PODs and must not exceed the size of a pointer"); |
65 | |
66 | //! Union to perform type casting |
67 | union value_storage |
68 | { |
69 | void* as_pointer; |
70 | T as_value; |
71 | }; |
72 | |
73 | public: |
74 | //! Default constructor |
75 | BOOST_DEFAULTED_FUNCTION(thread_specific(), {}) |
76 | //! Initializing constructor |
77 | thread_specific(T const& value) |
78 | { |
79 | set(value); |
80 | } |
81 | //! Assignment |
82 | thread_specific& operator= (T const& value) |
83 | { |
84 | set(value); |
85 | return *this; |
86 | } |
87 | |
88 | //! Accessor |
89 | T get() const |
90 | { |
91 | value_storage cast = {}; |
92 | cast.as_pointer = thread_specific_base::get_content(); |
93 | return cast.as_value; |
94 | } |
95 | |
96 | //! Setter |
97 | void set(T const& value) |
98 | { |
99 | value_storage cast = {}; |
100 | cast.as_value = value; |
101 | thread_specific_base::set_content(cast.as_pointer); |
102 | } |
103 | }; |
104 | |
105 | } // namespace aux |
106 | |
107 | BOOST_LOG_CLOSE_NAMESPACE // namespace log |
108 | |
109 | } // namespace boost |
110 | |
111 | #include <boost/log/detail/footer.hpp> |
112 | |
113 | #endif // !defined(BOOST_LOG_NO_THREADS) |
114 | |
115 | #endif // BOOST_LOG_DETAIL_THREAD_SPECIFIC_HPP_INCLUDED_ |
116 |