1 | /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 |
---|---|
2 | // extended_type_info_typeid.cpp: specific implementation of type info |
3 | // that is based on typeid |
4 | |
5 | // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . |
6 | // Use, modification and distribution is subject to the Boost Software |
7 | // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
8 | // http://www.boost.org/LICENSE_1_0.txt) |
9 | |
10 | // See http://www.boost.org for updates, documentation, and revision history. |
11 | |
12 | #include <algorithm> |
13 | #include <cstddef> // NULL |
14 | #include <set> |
15 | #include <typeinfo> |
16 | |
17 | #include <boost/assert.hpp> |
18 | #include <boost/core/no_exceptions_support.hpp> |
19 | |
20 | // it marks our code with proper attributes as being exported when |
21 | // we're compiling it while marking it import when just the headers |
22 | // is being included. |
23 | #define BOOST_SERIALIZATION_SOURCE |
24 | #include <boost/serialization/config.hpp> |
25 | #include <boost/serialization/singleton.hpp> |
26 | #include <boost/serialization/extended_type_info_typeid.hpp> |
27 | |
28 | namespace boost { |
29 | namespace serialization { |
30 | namespace typeid_system { |
31 | |
32 | #define EXTENDED_TYPE_INFO_TYPE_KEY 1 |
33 | |
34 | struct type_compare |
35 | { |
36 | bool |
37 | operator()( |
38 | const extended_type_info_typeid_0 * lhs, |
39 | const extended_type_info_typeid_0 * rhs |
40 | ) const { |
41 | return lhs->is_less_than(rhs: *rhs); |
42 | } |
43 | }; |
44 | |
45 | typedef std::multiset< |
46 | const extended_type_info_typeid_0 *, |
47 | type_compare |
48 | > tkmap; |
49 | |
50 | BOOST_SERIALIZATION_DECL bool |
51 | extended_type_info_typeid_0::is_less_than( |
52 | const boost::serialization::extended_type_info & rhs |
53 | ) const { |
54 | // shortcut for common case |
55 | if(this == & rhs) |
56 | return false; |
57 | return 0 != m_ti->before( |
58 | arg: *(static_cast<const extended_type_info_typeid_0 &>(rhs).m_ti) |
59 | ); |
60 | } |
61 | |
62 | BOOST_SERIALIZATION_DECL bool |
63 | extended_type_info_typeid_0::is_equal( |
64 | const boost::serialization::extended_type_info & rhs |
65 | ) const { |
66 | return |
67 | // note: std::type_info == operator returns an int !!! |
68 | // the following permits conversion to bool without a warning. |
69 | ! ( |
70 | * m_ti |
71 | != *(static_cast<const extended_type_info_typeid_0 &>(rhs).m_ti) |
72 | ) |
73 | ; |
74 | } |
75 | |
76 | BOOST_SERIALIZATION_DECL |
77 | extended_type_info_typeid_0::extended_type_info_typeid_0( |
78 | const char * key |
79 | ) : |
80 | extended_type_info(EXTENDED_TYPE_INFO_TYPE_KEY, key), |
81 | m_ti(NULL) |
82 | {} |
83 | |
84 | BOOST_SERIALIZATION_DECL |
85 | extended_type_info_typeid_0::~extended_type_info_typeid_0() |
86 | {} |
87 | |
88 | BOOST_SERIALIZATION_DECL void |
89 | extended_type_info_typeid_0::type_register(const std::type_info & ti){ |
90 | m_ti = & ti; |
91 | singleton<tkmap>::get_mutable_instance().insert(x: this); |
92 | } |
93 | |
94 | BOOST_SERIALIZATION_DECL void |
95 | extended_type_info_typeid_0::type_unregister() |
96 | { |
97 | if(NULL != m_ti){ |
98 | // note: previously this conditional was a runtime assertion with |
99 | // BOOST_ASSERT. We've changed it because we've discovered that at |
100 | // least one platform is not guaranteed to destroy singletons in |
101 | // reverse order of destruction. |
102 | // BOOST_ASSERT(! singleton<tkmap>::is_destroyed()); |
103 | if(! singleton<tkmap>::is_destroyed()){ |
104 | tkmap & x = singleton<tkmap>::get_mutable_instance(); |
105 | |
106 | // remove all entries in map which corresponds to this type |
107 | // make sure that we don't use any invalidated iterators |
108 | while(true){ |
109 | const tkmap::iterator & it = x.find(x: this); |
110 | if(it == x.end()) |
111 | break; |
112 | x.erase(position: it); |
113 | } |
114 | } |
115 | } |
116 | m_ti = NULL; |
117 | } |
118 | |
119 | #ifdef BOOST_MSVC |
120 | # pragma warning(push) |
121 | # pragma warning(disable : 4511 4512) |
122 | #endif |
123 | |
124 | // this derivation is used for creating search arguments |
125 | class extended_type_info_typeid_arg : |
126 | public extended_type_info_typeid_0 |
127 | { |
128 | void * construct(unsigned int /*count*/, ...) const BOOST_OVERRIDE { |
129 | BOOST_ASSERT(false); |
130 | return NULL; |
131 | } |
132 | void destroy(void const * const /*p*/) const BOOST_OVERRIDE { |
133 | BOOST_ASSERT(false); |
134 | } |
135 | public: |
136 | extended_type_info_typeid_arg(const std::type_info & ti) : |
137 | extended_type_info_typeid_0(NULL) |
138 | { |
139 | // note absence of self register and key as this is used only as |
140 | // search argument given a type_info reference and is not to |
141 | // be added to the map. |
142 | m_ti = & ti; |
143 | } |
144 | ~extended_type_info_typeid_arg() BOOST_OVERRIDE { |
145 | m_ti = NULL; |
146 | } |
147 | }; |
148 | |
149 | #ifdef BOOST_MSVC |
150 | # pragma warning(pop) |
151 | #endif |
152 | |
153 | BOOST_SERIALIZATION_DECL const extended_type_info * |
154 | extended_type_info_typeid_0::get_extended_type_info( |
155 | const std::type_info & ti |
156 | ) const { |
157 | typeid_system::extended_type_info_typeid_arg etia(ti); |
158 | const tkmap & t = singleton<tkmap>::get_const_instance(); |
159 | const tkmap::const_iterator it = t.find(x: & etia); |
160 | if(t.end() == it) |
161 | return NULL; |
162 | return *(it); |
163 | } |
164 | |
165 | } // namespace detail |
166 | } // namespace serialization |
167 | } // namespace boost |
168 |