summaryrefslogtreecommitdiff
path: root/boost/archive/detail/iserializer.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/archive/detail/iserializer.hpp')
-rw-r--r--boost/archive/detail/iserializer.hpp214
1 files changed, 120 insertions, 94 deletions
diff --git a/boost/archive/detail/iserializer.hpp b/boost/archive/detail/iserializer.hpp
index 53765af315..42d00a3350 100644
--- a/boost/archive/detail/iserializer.hpp
+++ b/boost/archive/detail/iserializer.hpp
@@ -2,7 +2,7 @@
#define BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP
// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#if defined(_MSC_VER)
# pragma once
#pragma inline_depth(511)
#pragma inline_recursion(on)
@@ -23,7 +23,6 @@
// See http://www.boost.org for updates, documentation, and revision history.
#include <new> // for placement new
-#include <memory> // for auto_ptr
#include <cstddef> // size_t, NULL
#include <boost/config.hpp>
@@ -58,14 +57,11 @@ namespace std{
#include <boost/type_traits/is_polymorphic.hpp>
#include <boost/serialization/assume_abstract.hpp>
-
#define DONT_USE_HAS_NEW_OPERATOR ( \
defined(__BORLANDC__) \
|| BOOST_WORKAROUND(__IBMCPP__, < 1210) \
- || defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) \
|| defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x590) \
)
-
#if ! DONT_USE_HAS_NEW_OPERATOR
#include <boost/type_traits/has_new_operator.hpp>
#endif
@@ -127,7 +123,7 @@ protected:
explicit iserializer() :
basic_iserializer(
boost::serialization::singleton<
- BOOST_DEDUCED_TYPENAME
+ typename
boost::serialization::type_info_implementation< T >::type
>::get_const_instance()
)
@@ -197,85 +193,84 @@ BOOST_DLLEXPORT void iserializer<Archive, T>::load_object_data(
# pragma warning(disable : 4511 4512)
#endif
-template<class Archive, class T>
-class pointer_iserializer :
- public basic_pointer_iserializer
-{
-private:
- virtual const basic_iserializer & get_basic_serializer() const {
- return boost::serialization::singleton<
- iserializer<Archive, T>
- >::get_const_instance();
- }
- BOOST_DLLEXPORT virtual void load_object_ptr(
- basic_iarchive & ar,
- void * & x,
- const unsigned int file_version
- ) const BOOST_USED;
-protected:
- // this should alway be a singleton so make the constructor protected
- pointer_iserializer();
- ~pointer_iserializer();
-};
-
-#ifdef BOOST_MSVC
-# pragma warning(pop)
-#endif
-
-// note trick to be sure that operator new is using class specific
-// version if such exists. Due to Peter Dimov.
-// note: the following fails if T has no default constructor.
-// otherwise it would have been ideal
-//struct heap_allocator : public T
-//{
-// T * invoke(){
-// return ::new(sizeof(T));
-// }
-//}
+// the purpose of this code is to allocate memory for an object
+// without requiring the constructor to be called. Presumably
+// the allocated object will be subsequently initialized with
+// "placement new".
+// note: we have the boost type trait has_new_operator but we
+// have no corresponding has_delete_operator. So we presume
+// that the former being true would imply that the a delete
+// operator is also defined for the class T.
template<class T>
-struct heap_allocator
-{
+struct heap_allocation {
// boost::has_new_operator< T > doesn't work on these compilers
#if DONT_USE_HAS_NEW_OPERATOR
// This doesn't handle operator new overload for class T
- static T * invoke(){
+ static T * invoke_new(){
return static_cast<T *>(operator new(sizeof(T)));
}
+ static void invoke_delete(T *t){
+ (operator delete(t));
+ }
#else
+ // note: we presume that a true value for has_new_operator
+ // implies the existence of a class specific delete operator as well
+ // as a class specific new operator.
struct has_new_operator {
- static T* invoke() {
+ static T * invoke_new() {
return static_cast<T *>((T::operator new)(sizeof(T)));
}
+ static void invoke_delete(T * t) {
+ // if compilation fails here, the likely cause that the class
+ // T has a class specific new operator but no class specific
+ // delete operator which matches the following signature. Fix
+ // your program to have this. Note that adding operator delete
+ // with only one parameter doesn't seem correct to me since
+ // the standard(3.7.4.2) says "
+ // "If a class T has a member deallocation function named
+ // 'operator delete' with exactly one parameter, then that function
+ // is a usual (non-placement) deallocation function" which I take
+ // to mean that it will call the destructor of type T which we don't
+ // want to do here.
+ // Note: reliance upon automatic conversion from T * to void * here
+ (T::operator delete)(t, sizeof(T));
+ }
};
struct doesnt_have_new_operator {
- static T* invoke() {
+ static T* invoke_new() {
return static_cast<T *>(operator new(sizeof(T)));
}
+ static void invoke_delete(T * t) {
+ // Note: I'm reliance upon automatic conversion from T * to void * here
+ (operator delete)(t);
+ }
};
- static T * invoke() {
- typedef BOOST_DEDUCED_TYPENAME
+ static T * invoke_new() {
+ typedef typename
+ mpl::eval_if<
+ boost::has_new_operator< T >,
+ mpl::identity<has_new_operator >,
+ mpl::identity<doesnt_have_new_operator >
+ >::type typex;
+ return typex::invoke_new();
+ }
+ static void invoke_delete(T *t) {
+ typedef typename
mpl::eval_if<
boost::has_new_operator< T >,
mpl::identity<has_new_operator >,
mpl::identity<doesnt_have_new_operator >
>::type typex;
- return typex::invoke();
+ typex::invoke_delete(t);
}
#endif
-};
-
-// due to Martin Ecker
-template <typename T>
-class auto_ptr_with_deleter
-{
-public:
- explicit auto_ptr_with_deleter(T* p) :
- m_p(p)
- {}
- ~auto_ptr_with_deleter(){
- if (m_p)
- boost::serialization::access::destroy(m_p);
+ explicit heap_allocation(){
+ m_p = invoke_new();
+ }
+ ~heap_allocation(){
+ if (0 != m_p)
+ invoke_delete(m_p);
}
T* get() const {
return m_p;
@@ -283,60 +278,88 @@ public:
T* release() {
T* p = m_p;
- m_p = NULL;
+ m_p = 0;
return p;
}
private:
T* m_p;
};
+template<class Archive, class T>
+class pointer_iserializer :
+ public basic_pointer_iserializer
+{
+private:
+ virtual void * heap_allocation() const {
+ detail::heap_allocation<T> h;
+ T * t = h.get();
+ h.release();
+ return t;
+ }
+ virtual const basic_iserializer & get_basic_serializer() const {
+ return boost::serialization::singleton<
+ iserializer<Archive, T>
+ >::get_const_instance();
+ }
+ BOOST_DLLEXPORT virtual void load_object_ptr(
+ basic_iarchive & ar,
+ void * x,
+ const unsigned int file_version
+ ) const BOOST_USED;
+protected:
+ // this should alway be a singleton so make the constructor protected
+ pointer_iserializer();
+ ~pointer_iserializer();
+};
+
+#ifdef BOOST_MSVC
+# pragma warning(pop)
+#endif
+
// note: BOOST_DLLEXPORT is so that code for polymorphic class
// serialized only through base class won't get optimized out
template<class Archive, class T>
BOOST_DLLEXPORT void pointer_iserializer<Archive, T>::load_object_ptr(
basic_iarchive & ar,
- void * & x,
+ void * t,
const unsigned int file_version
) const
{
Archive & ar_impl =
boost::serialization::smart_cast_reference<Archive &>(ar);
- auto_ptr_with_deleter< T > ap(heap_allocator< T >::invoke());
- if(NULL == ap.get())
- boost::serialization::throw_exception(std::bad_alloc()) ;
-
- T * t = ap.get();
- x = t;
+ // note that the above will throw std::bad_alloc if the allocation
+ // fails so we don't have to address this contingency here.
// catch exception during load_construct_data so that we don't
// automatically delete the t which is most likely not fully
// constructed
BOOST_TRY {
- // this addresses an obscure situtation that occurs when
+ // this addresses an obscure situation that occurs when
// load_constructor de-serializes something through a pointer.
ar.next_object_pointer(t);
boost::serialization::load_construct_data_adl<Archive, T>(
ar_impl,
- t,
+ static_cast<T *>(t),
file_version
);
}
BOOST_CATCH(...){
- ap.release();
+ // if we get here the load_construct failed. The heap_allocation
+ // will be automatically deleted so we don't have to do anything
+ // special here.
BOOST_RETHROW;
}
BOOST_CATCH_END
- ar_impl >> boost::serialization::make_nvp(NULL, * t);
- ap.release();
+ ar_impl >> boost::serialization::make_nvp(NULL, * static_cast<T *>(t));
}
template<class Archive, class T>
pointer_iserializer<Archive, T>::pointer_iserializer() :
basic_pointer_iserializer(
boost::serialization::singleton<
- BOOST_DEDUCED_TYPENAME
+ typename
boost::serialization::type_info_implementation< T >::type
>::get_const_instance()
)
@@ -405,7 +428,7 @@ struct load_non_pointer_type {
template<class T>
static void invoke(Archive & ar, T &t){
- typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
+ typedef typename mpl::eval_if<
// if its primitive
mpl::equal_to<
boost::serialization::implementation_level< T >,
@@ -413,7 +436,7 @@ struct load_non_pointer_type {
>,
mpl::identity<load_primitive>,
// else
- BOOST_DEDUCED_TYPENAME mpl::eval_if<
+ typename mpl::eval_if<
// class info / version
mpl::greater_equal<
boost::serialization::implementation_level< T >,
@@ -422,7 +445,7 @@ struct load_non_pointer_type {
// do standard load
mpl::identity<load_standard>,
// else
- BOOST_DEDUCED_TYPENAME mpl::eval_if<
+ typename mpl::eval_if<
// no tracking
mpl::equal_to<
boost::serialization::tracking_level< T >,
@@ -466,7 +489,7 @@ struct load_pointer_type {
// class pointer. Inhibiting code generation for this
// permits abstract base classes to be used - note: exception
// virtual serialize functions used for plug-ins
- typedef BOOST_DEDUCED_TYPENAME
+ typedef typename
mpl::eval_if<
boost::serialization::is_abstract<const T>,
boost::mpl::identity<abstract>,
@@ -482,18 +505,21 @@ struct load_pointer_type {
const T &
) {
// tweak the pointer back to the base class
- return static_cast<T *>(
- const_cast<void *>(
- boost::serialization::void_upcast(
- eti,
- boost::serialization::singleton<
- BOOST_DEDUCED_TYPENAME
- boost::serialization::type_info_implementation< T >::type
- >::get_const_instance(),
- t
- )
+ void * upcast = const_cast<void *>(
+ boost::serialization::void_upcast(
+ eti,
+ boost::serialization::singleton<
+ typename
+ boost::serialization::type_info_implementation< T >::type
+ >::get_const_instance(),
+ t
)
);
+ if(NULL == upcast)
+ boost::serialization::throw_exception(
+ archive_exception(archive_exception::unregistered_class)
+ );
+ return static_cast<T *>(upcast);
}
template<class T>
@@ -544,7 +570,7 @@ template<class Archive>
struct load_array_type {
template<class T>
static void invoke(Archive &ar, T &t){
- typedef BOOST_DEDUCED_TYPENAME remove_extent< T >::type value_type;
+ typedef typename remove_extent< T >::type value_type;
// convert integers to correct enum to load
// determine number of elements in the array. Consider the
@@ -576,13 +602,13 @@ inline void load(Archive & ar, T &t){
// handled below.
detail::check_const_loading< T >();
typedef
- BOOST_DEDUCED_TYPENAME mpl::eval_if<is_pointer< T >,
+ typename mpl::eval_if<is_pointer< T >,
mpl::identity<detail::load_pointer_type<Archive> >
,//else
- BOOST_DEDUCED_TYPENAME mpl::eval_if<is_array< T >,
+ typename mpl::eval_if<is_array< T >,
mpl::identity<detail::load_array_type<Archive> >
,//else
- BOOST_DEDUCED_TYPENAME mpl::eval_if<is_enum< T >,
+ typename mpl::eval_if<is_enum< T >,
mpl::identity<detail::load_enum_type<Archive> >
,//else
mpl::identity<detail::load_non_pointer_type<Archive> >