summaryrefslogtreecommitdiff
path: root/boost/log/utility/type_dispatch/dynamic_type_dispatcher.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/log/utility/type_dispatch/dynamic_type_dispatcher.hpp')
-rw-r--r--boost/log/utility/type_dispatch/dynamic_type_dispatcher.hpp154
1 files changed, 154 insertions, 0 deletions
diff --git a/boost/log/utility/type_dispatch/dynamic_type_dispatcher.hpp b/boost/log/utility/type_dispatch/dynamic_type_dispatcher.hpp
new file mode 100644
index 0000000000..8fa3c82d33
--- /dev/null
+++ b/boost/log/utility/type_dispatch/dynamic_type_dispatcher.hpp
@@ -0,0 +1,154 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2014.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file dynamic_type_dispatcher.hpp
+ * \author Andrey Semashev
+ * \date 15.04.2007
+ *
+ * The header contains implementation of the run-time type dispatcher.
+ */
+
+#ifndef BOOST_LOG_DYNAMIC_TYPE_DISPATCHER_HPP_INCLUDED_
+#define BOOST_LOG_DYNAMIC_TYPE_DISPATCHER_HPP_INCLUDED_
+
+#include <new>
+#include <memory>
+#include <map>
+#include <boost/ref.hpp>
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/smart_ptr/make_shared_object.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/visible_type.hpp>
+#include <boost/log/utility/type_info_wrapper.hpp>
+#include <boost/log/utility/type_dispatch/type_dispatcher.hpp>
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+/*!
+ * \brief A dynamic type dispatcher
+ *
+ * The type dispatcher can be used to pass objects of arbitrary types from one
+ * component to another. With regard to the library, the type dispatcher
+ * can be used to extract attribute values.
+ *
+ * The dynamic type dispatcher can be initialized in run time and, therefore,
+ * can support different types, depending on runtime conditions. Each
+ * supported type is associated with a functional object that will be called
+ * when an object of the type is dispatched.
+ */
+class dynamic_type_dispatcher :
+ public type_dispatcher
+{
+private:
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ template< typename T, typename VisitorT >
+ class callback_impl :
+ public callback_base
+ {
+ private:
+ VisitorT m_Visitor;
+
+ public:
+ explicit callback_impl(VisitorT const& visitor) : m_Visitor(visitor)
+ {
+ this->m_pVisitor = (void*)boost::addressof(m_Visitor);
+ typedef void (*trampoline_t)(void*, T const&);
+ 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");
+ union
+ {
+ void* as_pvoid;
+ trampoline_t as_trampoline;
+ }
+ caster;
+ caster.as_trampoline = &callback_base::trampoline< VisitorT, T >;
+ this->m_pTrampoline = caster.as_pvoid;
+ }
+ };
+#endif // BOOST_LOG_DOXYGEN_PASS
+
+ //! The dispatching map
+ typedef std::map< type_info_wrapper, shared_ptr< callback_base > > dispatching_map;
+ dispatching_map m_DispatchingMap;
+
+public:
+ /*!
+ * Default constructor
+ */
+ dynamic_type_dispatcher() : type_dispatcher(&dynamic_type_dispatcher::get_callback)
+ {
+ }
+
+ /*!
+ * Copy constructor
+ */
+ dynamic_type_dispatcher(dynamic_type_dispatcher const& that) :
+ type_dispatcher(static_cast< type_dispatcher const& >(that)),
+ m_DispatchingMap(that.m_DispatchingMap)
+ {
+ }
+
+ /*!
+ * Copy assignment
+ */
+ dynamic_type_dispatcher& operator= (dynamic_type_dispatcher const& that)
+ {
+ m_DispatchingMap = that.m_DispatchingMap;
+ return *this;
+ }
+
+ /*!
+ * The method registers a new type
+ *
+ * \param visitor Function object that will be associated with the type \c T
+ */
+ template< typename T, typename VisitorT >
+ void register_type(VisitorT const& visitor)
+ {
+ boost::shared_ptr< callback_base > p(
+ boost::make_shared< callback_impl< T, VisitorT > >(boost::cref(visitor)));
+
+ type_info_wrapper wrapper(typeid(aux::visible_type< T >));
+ m_DispatchingMap[wrapper].swap(p);
+ }
+
+ /*!
+ * The method returns the number of registered types
+ */
+ dispatching_map::size_type registered_types_count() const
+ {
+ return m_DispatchingMap.size();
+ }
+
+private:
+#ifndef BOOST_LOG_DOXYGEN_PASS
+ static callback_base get_callback(type_dispatcher* p, std::type_info const& type)
+ {
+ dynamic_type_dispatcher* const self = static_cast< dynamic_type_dispatcher* >(p);
+ type_info_wrapper wrapper(type);
+ dispatching_map::iterator it = self->m_DispatchingMap.find(wrapper);
+ if (it != self->m_DispatchingMap.end())
+ return *it->second;
+ else
+ return callback_base();
+ }
+#endif // BOOST_LOG_DOXYGEN_PASS
+};
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_DYNAMIC_TYPE_DISPATCHER_HPP_INCLUDED_