]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/log/include/boost/log/utility/type_dispatch/dynamic_type_dispatcher.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / log / include / boost / log / utility / type_dispatch / dynamic_type_dispatcher.hpp
CommitLineData
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
33namespace boost {
34
35BOOST_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 */
49class dynamic_type_dispatcher :
50 public type_dispatcher
51{
52private:
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
83public:
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
132private:
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
146BOOST_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_