dynamic_type_dispatcher.hpp 4.4 KB

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