serialize_tracked_address.hpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. /* Copyright 2023 Joaquin M Lopez Munoz.
  2. * Distributed under the Boost Software License, Version 1.0.
  3. * (See accompanying file LICENSE_1_0.txt or copy at
  4. * http://www.boost.org/LICENSE_1_0.txt)
  5. *
  6. * See https://www.boost.org/libs/unordered for library home page.
  7. */
  8. #ifndef BOOST_UNORDERED_DETAIL_SERIALIZE_TRACKED_ADDRESS_HPP
  9. #define BOOST_UNORDERED_DETAIL_SERIALIZE_TRACKED_ADDRESS_HPP
  10. #include <boost/unordered/detail/bad_archive_exception.hpp>
  11. #include <boost/core/pointer_traits.hpp>
  12. #include <boost/core/serialization.hpp>
  13. #include <boost/throw_exception.hpp>
  14. #include <type_traits>
  15. namespace boost{
  16. namespace unordered{
  17. namespace detail{
  18. /* Tracked address serialization to support iterator serialization as described
  19. * in serialize_container.hpp. The underlying technique is to reinterpret_cast
  20. * T pointers to serialization_tracker<T> pointers, which, when dereferenced
  21. * and serialized, do not emit any serialization payload to the
  22. * archive, but activate object tracking on the relevant addresses for later
  23. * use with serialize_tracked_address().
  24. */
  25. template<typename T>
  26. struct serialization_tracker
  27. {
  28. /* An attempt to construct a serialization_tracker means a stray address
  29. * in the archive, that is, one without a previously tracked address.
  30. */
  31. serialization_tracker(){throw_exception(bad_archive_exception());}
  32. template<typename Archive>
  33. void serialize(Archive&,unsigned int){} /* no data emitted */
  34. };
  35. template<typename Archive,typename Ptr>
  36. void track_address(Archive& ar,Ptr p)
  37. {
  38. typedef typename boost::pointer_traits<Ptr> ptr_traits;
  39. typedef typename std::remove_const<
  40. typename ptr_traits::element_type>::type element_type;
  41. if(p){
  42. ar&core::make_nvp(
  43. "address",
  44. *reinterpret_cast<serialization_tracker<element_type>*>(
  45. const_cast<element_type*>(
  46. boost::to_address(p))));
  47. }
  48. }
  49. template<typename Archive,typename Ptr>
  50. void serialize_tracked_address(Archive& ar,Ptr& p,std::true_type /* save */)
  51. {
  52. typedef typename boost::pointer_traits<Ptr> ptr_traits;
  53. typedef typename std::remove_const<
  54. typename ptr_traits::element_type>::type element_type;
  55. typedef serialization_tracker<element_type> tracker;
  56. tracker* pt=
  57. const_cast<tracker*>(
  58. reinterpret_cast<const tracker*>(
  59. const_cast<const element_type*>(
  60. boost::to_address(p))));
  61. ar<<core::make_nvp("pointer",pt);
  62. }
  63. template<typename Archive,typename Ptr>
  64. void serialize_tracked_address(Archive& ar,Ptr& p,std::false_type /* load */)
  65. {
  66. typedef typename boost::pointer_traits<Ptr> ptr_traits;
  67. typedef typename std::remove_const<
  68. typename ptr_traits::element_type>::type element_type;
  69. typedef serialization_tracker<element_type> tracker;
  70. tracker* pt;
  71. ar>>core::make_nvp("pointer",pt);
  72. element_type* pn=const_cast<element_type*>(
  73. reinterpret_cast<const element_type*>(
  74. const_cast<const tracker*>(pt)));
  75. p=pn?ptr_traits::pointer_to(*pn):0;
  76. }
  77. template<typename Archive,typename Ptr>
  78. void serialize_tracked_address(Archive& ar,Ptr& p)
  79. {
  80. serialize_tracked_address(
  81. ar,p,
  82. std::integral_constant<bool,Archive::is_saving::value>());
  83. }
  84. } /* namespace detail */
  85. } /* namespace unordered */
  86. } /* namespace boost */
  87. #endif