Ticket #1418: archive-cast.patch.boost_1_42_0

File archive-cast.patch.boost_1_42_0, 16.7 KB (added by kab@…, 13 years ago)

update patch for boost 1.42

Line 
1diff -Naur ../boost_1_42_0-orig//boost/archive/detail/archive_cast.hpp ./boost/archive/detail/archive_cast.hpp
2--- ../boost_1_42_0-orig//boost/archive/detail/archive_cast.hpp 1969-12-31 19:00:00.000000000 -0500
3+++ ./boost/archive/detail/archive_cast.hpp 2010-03-20 22:01:49.000000000 -0400
4@@ -0,0 +1,113 @@
5+#ifndef BOOST_ARCHIVE_DETAIL_ARCHIVE_CAST_HPP
6+#define BOOST_ARCHIVE_DETAIL_ARCHIVE_CAST_HPP
7+
8+// MS compatible compilers support #pragma once
9+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
10+# pragma once
11+#endif
12+
13+// archive_cast.hpp
14+
15+// (C) Copyright 2007 Kim Barrett - kab@irobot.com
16+// Use, modification and distribution is subject to the Boost Software
17+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
18+// http://www.boost.org/LICENSE_1_0.txt)
19+
20+#include <boost/config.hpp>
21+#include <boost/serialization/smart_cast.hpp>
22+#include <boost/type_traits/is_base_and_derived.hpp>
23+
24+#include <boost/archive/detail/abi_prefix.hpp> // must be the last header
25+
26+// helper for [i,o]serializers, allowing them to route operation to the
27+// appropriate specialized archive class. the purpose of archive_cast is to
28+// provide the serializer with a means of converting a reference to the
29+// basic_[i,o]archive to the appropriate archive class for further
30+// serialization.
31+//
32+// the Archive type must be the same type for all serialization calls
33+// applied to a given archive. if the archive is non-polymorphic, the Archive
34+// type must always be the most derived type of the archive. if the archive
35+// is polymorphic, the Archive type should always be the polymorphic archive
36+// type, else there would be little point in using a polymorphic archive type.
37+//
38+// in the non-polymorphic case, because Archive is the most derived archive
39+// type, which is (indirectly) derived from the basic archive class, the
40+// operation is a (supposedly safe) downcast.
41+//
42+// in the polymorphic case, Archive is the polymorphic archive class (or
43+// possibly something derived from it), and the obvious conversion is a
44+// dynamic_cast. however, in this case that dynamic_cast is a cross-cast,
45+// because the polymorphic archive class and the basic archive class are not
46+// in a base and derived relationship (in either order). cross-casts may be
47+// extremely expensive on some platforms, so a different approach is desired.
48+//
49+// archive_caster provides deferrable conversion of a basic_[i,o]archive to
50+// Archive. the cast function returns the result of that conversion as a
51+// void*. the conversion to void* permits the value to be stored in a location
52+// that has no information about Archive, with a later static cast from that
53+// void* to Archive*.
54+//
55+// archive_cast_pointer provides the customization point for the
56+// basic_[i,o]archive classes. the intended implementation is to cache the
57+// result of the caster in the basic archive on the first call, and use the
58+// previously cached result thereafter.
59+//
60+// archive_cast_impl provides a level of indirection so that archive_cast
61+// only instantiates the archive_caster template when actually needed, and
62+// not in the case where Archive is derived from From.
63+
64+namespace boost {
65+namespace archive {
66+namespace detail {
67+
68+template<class Archive, class From>
69+struct BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) archive_caster {
70+ // out of line implementation in impl/archive_cast.ipp.
71+ static void* cast(From& ar);
72+};
73+
74+template<class From>
75+struct BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) archive_cast_pointer {
76+ // out of line implementations for each relevant From class
77+ static void* get(From& ar, void* (*caster)(From& ar));
78+};
79+
80+template<class From, bool is_derived>
81+struct BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) archive_cast_impl;
82+
83+template<class From>
84+struct archive_cast_impl<From, true> { // Archive derived from From
85+ template<class Archive>
86+ static Archive& cast(From& ar) {
87+ return boost::serialization::smart_cast_reference<Archive&>(ar);
88+ }
89+};
90+
91+template<class From>
92+struct archive_cast_impl<From, false> { // Archive not derived from From
93+ template<class Archive>
94+ static Archive& cast(From& ar) {
95+ return *static_cast<Archive*>(
96+ archive_cast_pointer<From>::get(
97+ ar,
98+ archive_caster<Archive, From>::cast));
99+ }
100+};
101+
102+template<class Archive, class From>
103+inline Archive& archive_cast(From& ar) {
104+ // select implementation based on whether Archive is derived from From
105+ return archive_cast_impl<
106+ From,
107+ boost::is_base_and_derived<From, Archive>::value
108+ >::template cast<Archive>(ar);
109+}
110+
111+} // namespace detail
112+} // namespace archive
113+} // namespace boost
114+
115+#include <boost/archive/detail/abi_suffix.hpp> // pops abi_prefix.hpp pragmas
116+
117+#endif // include guard
118diff -Naur ../boost_1_42_0-orig//boost/archive/detail/basic_iarchive.hpp ./boost/archive/detail/basic_iarchive.hpp
119--- ../boost_1_42_0-orig//boost/archive/detail/basic_iarchive.hpp 2009-12-14 18:52:51.000000000 -0500
120+++ ./boost/archive/detail/basic_iarchive.hpp 2010-03-20 21:53:40.000000000 -0400
121@@ -25,6 +25,7 @@
122 #include <boost/type_traits/broken_compiler_spec.hpp>
123 #include <boost/serialization/tracking_enum.hpp>
124 #include <boost/archive/basic_archive.hpp>
125+#include <boost/archive/detail/archive_cast.hpp>
126 #include <boost/archive/detail/decl.hpp>
127 #include <boost/archive/detail/abi_prefix.hpp> // must be the last header
128
129@@ -44,6 +45,7 @@
130 class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iarchive :
131 private boost::noncopyable
132 {
133+ friend class archive_cast_pointer<basic_iarchive>;
134 friend class basic_iarchive_impl;
135 // hide implementation of this class to minimize header conclusion
136 // in client code. I couldn't used scoped pointer with borland
137diff -Naur ../boost_1_42_0-orig//boost/archive/detail/basic_oarchive.hpp ./boost/archive/detail/basic_oarchive.hpp
138--- ../boost_1_42_0-orig//boost/archive/detail/basic_oarchive.hpp 2009-12-05 01:32:01.000000000 -0500
139+++ ./boost/archive/detail/basic_oarchive.hpp 2010-03-20 21:53:40.000000000 -0400
140@@ -26,6 +26,7 @@
141 // #include <boost/scoped_ptr.hpp>
142
143 #include <boost/archive/basic_archive.hpp>
144+#include <boost/archive/detail/archive_cast.hpp>
145 #include <boost/serialization/tracking_enum.hpp>
146
147 #include <boost/archive/detail/abi_prefix.hpp> // must be the last header
148@@ -46,6 +47,7 @@
149 class BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oarchive :
150 private boost::noncopyable
151 {
152+ friend class archive_cast_pointer<basic_oarchive>;
153 friend class basic_oarchive_impl;
154 // hide implementation of this class to minimize header conclusion
155 // in client code. note: borland can't use scoped_ptr
156diff -Naur ../boost_1_42_0-orig//boost/archive/detail/iserializer.hpp ./boost/archive/detail/iserializer.hpp
157--- ../boost_1_42_0-orig//boost/archive/detail/iserializer.hpp 2009-12-14 18:52:51.000000000 -0500
158+++ ./boost/archive/detail/iserializer.hpp 2010-03-20 21:53:40.000000000 -0400
159@@ -85,6 +85,7 @@
160 // the following is need only for dynamic cast of polymorphic pointers
161 #include <boost/archive/archive_exception.hpp>
162 #include <boost/archive/detail/basic_iarchive.hpp>
163+#include <boost/archive/detail/archive_cast.hpp>
164 #include <boost/archive/detail/basic_iserializer.hpp>
165 #include <boost/archive/detail/basic_pointer_iserializer.hpp>
166 #include <boost/archive/detail/archive_serializer_map.hpp>
167@@ -180,7 +181,7 @@
168 // make sure call is routed through the higest interface that might
169 // be specialized by the user.
170 boost::serialization::serialize_adl(
171- boost::serialization::smart_cast_reference<Archive &>(ar),
172+ archive_cast<Archive>(ar),
173 * static_cast<T *>(x),
174 file_version
175 );
176@@ -293,8 +294,7 @@
177 const unsigned int file_version
178 ) const
179 {
180- Archive & ar_impl =
181- boost::serialization::smart_cast_reference<Archive &>(ar);
182+ Archive & ar_impl = archive_cast<Archive>(ar);
183
184 auto_ptr_with_deleter<T> ap(heap_allocator<T>::invoke());
185 if(NULL == ap.get())
186diff -Naur ../boost_1_42_0-orig//boost/archive/detail/oserializer.hpp ./boost/archive/detail/oserializer.hpp
187--- ../boost_1_42_0-orig//boost/archive/detail/oserializer.hpp 2009-12-05 01:32:01.000000000 -0500
188+++ ./boost/archive/detail/oserializer.hpp 2010-03-20 21:53:40.000000000 -0400
189@@ -61,6 +61,7 @@
190
191 #include <boost/archive/archive_exception.hpp>
192 #include <boost/archive/detail/basic_oarchive.hpp>
193+#include <boost/archive/detail/archive_cast.hpp>
194 #include <boost/archive/detail/basic_oserializer.hpp>
195 #include <boost/archive/detail/basic_pointer_oserializer.hpp>
196 #include <boost/archive/detail/archive_serializer_map.hpp>
197@@ -146,7 +147,7 @@
198 // be specialized by the user.
199 BOOST_STATIC_ASSERT(boost::is_const<T>::value == false);
200 boost::serialization::serialize_adl(
201- boost::serialization::smart_cast_reference<Archive &>(ar),
202+ archive_cast<Archive>(ar),
203 * static_cast<T *>(const_cast<void *>(x)),
204 version()
205 );
206@@ -191,8 +192,7 @@
207 // be specialized by the user.
208 T * t = static_cast<T *>(const_cast<void *>(x));
209 const unsigned int file_version = boost::serialization::version<T>::value;
210- Archive & ar_impl
211- = boost::serialization::smart_cast_reference<Archive &>(ar);
212+ Archive & ar_impl = archive_cast<Archive>(ar);
213 boost::serialization::save_construct_data_adl<Archive, T>(
214 ar_impl,
215 t,
216diff -Naur ../boost_1_42_0-orig//boost/archive/impl/archive_cast.ipp ./boost/archive/impl/archive_cast.ipp
217--- ../boost_1_42_0-orig//boost/archive/impl/archive_cast.ipp 1969-12-31 19:00:00.000000000 -0500
218+++ ./boost/archive/impl/archive_cast.ipp 2010-03-20 21:53:40.000000000 -0400
219@@ -0,0 +1,23 @@
220+// archive_cast.ipp
221+
222+// (C) Copyright 2007 Kim Barrett - kab@irobot.com
223+// Use, modification and distribution is subject to the Boost Software
224+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
225+// http://www.boost.org/LICENSE_1_0.txt)
226+
227+#include <boost/config.hpp> // msvc 6.0 needs this for warning suppression
228+
229+#include <boost/archive/detail/archive_cast.hpp>
230+
231+namespace boost {
232+namespace archive {
233+namespace detail {
234+
235+template<class Archive, class From>
236+void* archive_caster<Archive, From>::cast(From& ar) {
237+ return & dynamic_cast<Archive &>(ar);
238+}
239+
240+} // namespace detail
241+} // namespace archive
242+} // namespace boost
243diff -Naur ../boost_1_42_0-orig//libs/serialization/src/basic_iarchive.cpp ./libs/serialization/src/basic_iarchive.cpp
244--- ../boost_1_42_0-orig//libs/serialization/src/basic_iarchive.cpp 2009-12-14 18:48:21.000000000 -0500
245+++ ./libs/serialization/src/basic_iarchive.cpp 2010-03-20 21:53:40.000000000 -0400
246@@ -38,6 +38,7 @@
247 #include <boost/archive/detail/basic_iserializer.hpp>
248 #include <boost/archive/detail/basic_pointer_iserializer.hpp>
249 #include <boost/archive/detail/basic_iarchive.hpp>
250+#include <boost/archive/detail/archive_cast.hpp>
251
252 #include <boost/archive/detail/auto_link_archive.hpp>
253
254@@ -49,8 +50,11 @@
255
256 class basic_iarchive_impl {
257 friend class basic_iarchive;
258+ friend class archive_cast_pointer<basic_iarchive>;
259 version_type m_archive_library_version;
260 unsigned int m_flags;
261+ void* (*m_cached_archive_caster)(basic_iarchive&);
262+ void* m_cached_archive_cast_pointer;
263
264 //////////////////////////////////////////////////////////////////////
265 // information about each serialized object loaded
266@@ -164,6 +168,8 @@
267 basic_iarchive_impl(unsigned int flags) :
268 m_archive_library_version(BOOST_ARCHIVE_VERSION()),
269 m_flags(flags),
270+ m_cached_archive_caster(NULL),
271+ m_cached_archive_cast_pointer(NULL),
272 moveable_objects_start(0),
273 moveable_objects_end(0),
274 moveable_objects_recent(0),
275@@ -581,6 +587,31 @@
276 return pimpl->m_flags;
277 }
278
279+// this is identical to the corresponding basic_oarchive function.
280+// it would be nice if they could be merged into one parameterized definition,
281+// but doing so seems more work than accepting and noting the duplication.
282+template<>
283+BOOST_ARCHIVE_DECL(void*)
284+archive_cast_pointer<basic_iarchive>::get(
285+ basic_iarchive& ar, void* (*caster)(basic_iarchive&))
286+{
287+ void* result = ar.pimpl->m_cached_archive_cast_pointer;
288+ if (result) {
289+ // already cached.
290+ // if debug build, verify called with same caster.
291+ assert(caster == ar.pimpl->m_cached_archive_caster);
292+ // if debug build, verify cached result matches caster result.
293+ // otherwise, assume it does and skip expensive cast
294+ assert(result == caster(ar));
295+ } else {
296+ // on first call, use the caster's result and cache for later reuse.
297+ result = caster(ar);
298+ ar.pimpl->m_cached_archive_caster = caster;
299+ ar.pimpl->m_cached_archive_cast_pointer = result;
300+ }
301+ return result;
302+}
303+
304 } // namespace detail
305 } // namespace archive
306 } // namespace boost
307diff -Naur ../boost_1_42_0-orig//libs/serialization/src/basic_oarchive.cpp ./libs/serialization/src/basic_oarchive.cpp
308--- ../boost_1_42_0-orig//libs/serialization/src/basic_oarchive.cpp 2009-12-05 01:34:10.000000000 -0500
309+++ ./libs/serialization/src/basic_oarchive.cpp 2010-03-20 21:53:40.000000000 -0400
310@@ -27,6 +27,7 @@
311 #include <boost/archive/detail/basic_oserializer.hpp>
312 #include <boost/archive/detail/basic_pointer_oserializer.hpp>
313 #include <boost/archive/detail/basic_oarchive.hpp>
314+#include <boost/archive/detail/archive_cast.hpp>
315 #include <boost/archive/archive_exception.hpp>
316 #include <boost/serialization/extended_type_info.hpp>
317
318@@ -43,7 +44,10 @@
319
320 class basic_oarchive_impl {
321 friend class basic_oarchive;
322+ friend class archive_cast_pointer<basic_oarchive>;
323 unsigned int m_flags;
324+ void* (*m_cached_archive_caster)(basic_oarchive&);
325+ void* m_cached_archive_cast_pointer;
326
327 //////////////////////////////////////////////////////////////////////
328 // information about each serialized object saved
329@@ -138,6 +142,8 @@
330
331 basic_oarchive_impl(unsigned int flags) :
332 m_flags(flags),
333+ m_cached_archive_caster(NULL),
334+ m_cached_archive_cast_pointer(NULL),
335 pending_object(NULL),
336 pending_bos(NULL)
337 {}
338@@ -459,6 +465,31 @@
339 basic_oarchive::end_preamble(){
340 }
341
342+// this is identical to the corresponding basic_iarchive function.
343+// it would be nice if they could be merged into one parameterized definition,
344+// but doing so seems more work than accepting and noting the duplication.
345+template<>
346+BOOST_ARCHIVE_DECL(void*)
347+archive_cast_pointer<basic_oarchive>::get(
348+ basic_oarchive& ar, void* (*caster)(basic_oarchive&))
349+{
350+ void* result = ar.pimpl->m_cached_archive_cast_pointer;
351+ if (result) {
352+ // already cached.
353+ // if debug build, verify called with same caster.
354+ assert(caster == ar.pimpl->m_cached_archive_caster);
355+ // if debug build, verify cached result matches caster result.
356+ // otherwise, assume it does and skip expensive cast
357+ assert(result == caster(ar));
358+ } else {
359+ // on first call, use the caster's result and cache for later reuse.
360+ result = caster(ar);
361+ ar.pimpl->m_cached_archive_caster = caster;
362+ ar.pimpl->m_cached_archive_cast_pointer = result;
363+ }
364+ return result;
365+}
366+
367 } // namespace detail
368 } // namespace archive
369 } // namespace boost
370diff -Naur ../boost_1_42_0-orig//libs/serialization/src/polymorphic_iarchive.cpp ./libs/serialization/src/polymorphic_iarchive.cpp
371--- ../boost_1_42_0-orig//libs/serialization/src/polymorphic_iarchive.cpp 2009-08-01 19:32:25.000000000 -0400
372+++ ./libs/serialization/src/polymorphic_iarchive.cpp 2010-03-20 21:53:40.000000000 -0400
373@@ -18,11 +18,15 @@
374 #include <boost/archive/impl/archive_serializer_map.ipp>
375 #include <boost/archive/polymorphic_iarchive.hpp>
376
377+#include <boost/archive/impl/archive_cast.ipp>
378+#include <boost/archive/detail/basic_iarchive.hpp>
379+
380 namespace boost {
381 namespace archive {
382 namespace detail {
383
384 template class archive_serializer_map<polymorphic_iarchive>;
385+template class archive_caster<polymorphic_iarchive, basic_iarchive>;
386
387 } // detail
388 } // archive
389diff -Naur ../boost_1_42_0-orig//libs/serialization/src/polymorphic_oarchive.cpp ./libs/serialization/src/polymorphic_oarchive.cpp
390--- ../boost_1_42_0-orig//libs/serialization/src/polymorphic_oarchive.cpp 2009-09-19 22:18:02.000000000 -0400
391+++ ./libs/serialization/src/polymorphic_oarchive.cpp 2010-03-20 21:53:40.000000000 -0400
392@@ -18,11 +18,15 @@
393 #include <boost/archive/impl/archive_serializer_map.ipp>
394 #include <boost/archive/polymorphic_oarchive.hpp>
395
396+#include <boost/archive/impl/archive_cast.ipp>
397+#include <boost/archive/detail/basic_oarchive.hpp>
398+
399 namespace boost {
400 namespace archive {
401 namespace detail {
402
403 template class archive_serializer_map<polymorphic_oarchive>;
404+template class archive_caster<polymorphic_oarchive, basic_oarchive>;
405
406 } // detail
407 } // archive