]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 dynamic_type_dispatcher.hpp | |
9 | * \author Andrey Semashev | |
10 | * \date 15.04.2007 | |
11 | * | |
12 | * The header contains implementation of the run-time type dispatcher. | |
13 | */ | |
14 | ||
15 | #ifndef BOOST_LOG_DYNAMIC_TYPE_DISPATCHER_HPP_INCLUDED_ | |
16 | #define BOOST_LOG_DYNAMIC_TYPE_DISPATCHER_HPP_INCLUDED_ | |
17 | ||
18 | #include <new> | |
19 | #include <memory> | |
20 | #include <map> | |
21 | #include <boost/ref.hpp> | |
22 | #include <boost/type_index.hpp> | |
23 | #include <boost/smart_ptr/shared_ptr.hpp> | |
24 | #include <boost/smart_ptr/make_shared_object.hpp> | |
25 | #include <boost/log/detail/config.hpp> | |
26 | #include <boost/log/utility/type_dispatch/type_dispatcher.hpp> | |
27 | #include <boost/log/detail/header.hpp> | |
28 | ||
29 | #ifdef BOOST_HAS_PRAGMA_ONCE | |
30 | #pragma once | |
31 | #endif | |
32 | ||
33 | namespace boost { | |
34 | ||
35 | BOOST_LOG_OPEN_NAMESPACE | |
36 | ||
37 | /*! | |
38 | * \brief A dynamic type dispatcher | |
39 | * | |
40 | * The type dispatcher can be used to pass objects of arbitrary types from one | |
41 | * component to another. With regard to the library, the type dispatcher | |
42 | * can be used to extract attribute values. | |
43 | * | |
44 | * The dynamic type dispatcher can be initialized in run time and, therefore, | |
45 | * can support different types, depending on runtime conditions. Each | |
46 | * supported type is associated with a functional object that will be called | |
47 | * when an object of the type is dispatched. | |
48 | */ | |
49 | class dynamic_type_dispatcher : | |
50 | public type_dispatcher | |
51 | { | |
52 | private: | |
53 | #ifndef BOOST_LOG_DOXYGEN_PASS | |
54 | template< typename T, typename VisitorT > | |
55 | class callback_impl : | |
56 | public callback_base | |
57 | { | |
58 | private: | |
59 | VisitorT m_Visitor; | |
60 | ||
61 | public: | |
62 | explicit callback_impl(VisitorT const& visitor) : m_Visitor(visitor) | |
63 | { | |
64 | this->m_pVisitor = (void*)boost::addressof(m_Visitor); | |
65 | typedef void (*trampoline_t)(void*, T const&); | |
66 | BOOST_STATIC_ASSERT_MSG(sizeof(trampoline_t) == sizeof(void*), "Boost.Log: Unsupported platform, the size of a function pointer differs from the size of a pointer"); | |
67 | union | |
68 | { | |
69 | void* as_pvoid; | |
70 | trampoline_t as_trampoline; | |
71 | } | |
72 | caster; | |
73 | caster.as_trampoline = (trampoline_t)&callback_base::trampoline< VisitorT, T >; | |
74 | this->m_pTrampoline = caster.as_pvoid; | |
75 | } | |
76 | }; | |
77 | #endif // BOOST_LOG_DOXYGEN_PASS | |
78 | ||
79 | //! The dispatching map | |
80 | typedef std::map< typeindex::type_index, shared_ptr< callback_base > > dispatching_map; | |
81 | dispatching_map m_DispatchingMap; | |
82 | ||
83 | public: | |
84 | /*! | |
85 | * Default constructor | |
86 | */ | |
87 | dynamic_type_dispatcher() : type_dispatcher(&dynamic_type_dispatcher::get_callback) | |
88 | { | |
89 | } | |
90 | ||
91 | /*! | |
92 | * Copy constructor | |
93 | */ | |
94 | dynamic_type_dispatcher(dynamic_type_dispatcher const& that) : | |
95 | type_dispatcher(static_cast< type_dispatcher const& >(that)), | |
96 | m_DispatchingMap(that.m_DispatchingMap) | |
97 | { | |
98 | } | |
99 | ||
100 | /*! | |
101 | * Copy assignment | |
102 | */ | |
103 | dynamic_type_dispatcher& operator= (dynamic_type_dispatcher const& that) | |
104 | { | |
105 | m_DispatchingMap = that.m_DispatchingMap; | |
106 | return *this; | |
107 | } | |
108 | ||
109 | /*! | |
110 | * The method registers a new type | |
111 | * | |
112 | * \param visitor Function object that will be associated with the type \c T | |
113 | */ | |
114 | template< typename T, typename VisitorT > | |
115 | void register_type(VisitorT const& visitor) | |
116 | { | |
117 | boost::shared_ptr< callback_base > p( | |
118 | boost::make_shared< callback_impl< T, VisitorT > >(boost::cref(visitor))); | |
119 | ||
120 | typeindex::type_index wrapper(typeindex::type_id< T >()); | |
121 | m_DispatchingMap[wrapper].swap(p); | |
122 | } | |
123 | ||
124 | /*! | |
125 | * The method returns the number of registered types | |
126 | */ | |
127 | dispatching_map::size_type registered_types_count() const | |
128 | { | |
129 | return m_DispatchingMap.size(); | |
130 | } | |
131 | ||
132 | private: | |
133 | #ifndef BOOST_LOG_DOXYGEN_PASS | |
134 | static callback_base get_callback(type_dispatcher* p, typeindex::type_index type) | |
135 | { | |
136 | dynamic_type_dispatcher* const self = static_cast< dynamic_type_dispatcher* >(p); | |
137 | dispatching_map::iterator it = self->m_DispatchingMap.find(type); | |
138 | if (it != self->m_DispatchingMap.end()) | |
139 | return *it->second; | |
140 | else | |
141 | return callback_base(); | |
142 | } | |
143 | #endif // BOOST_LOG_DOXYGEN_PASS | |
144 | }; | |
145 | ||
146 | BOOST_LOG_CLOSE_NAMESPACE // namespace log | |
147 | ||
148 | } // namespace boost | |
149 | ||
150 | #include <boost/log/detail/footer.hpp> | |
151 | ||
152 | #endif // BOOST_LOG_DYNAMIC_TYPE_DISPATCHER_HPP_INCLUDED_ |