12 #ifndef SST_CORE_SERIALIZATION_IMPL_SERIALIZE_SHARED_PTR_H 13 #define SST_CORE_SERIALIZATION_IMPL_SERIALIZE_SHARED_PTR_H 15 #ifndef SST_INCLUDING_SERIALIZE_H 17 "The header file sst/core/serialization/impl/serialize_shared_ptr.h should not be directly included as it is not part of the stable public API. The file is included in sst/core/serialization/serialize.h" 20 #include "sst/core/output.h" 21 #include "sst/core/serialization/serializer.h" 25 #include <type_traits> 34 template <
template <
class>
class PTR_TEMPLATE>
35 constexpr
auto ptr_string =
36 [] { static_assert(!is_same_template_v<PTR_TEMPLATE, PTR_TEMPLATE>,
"Bad ptr_string template argument"); };
39 constexpr
inline char ptr_string<std::weak_ptr>[] =
"weak_ptr";
42 constexpr
inline char ptr_string<std::shared_ptr>[] =
"shared_ptr";
44 template <
template <
class>
class PTR_TEMPLATE>
45 constexpr
auto array_size_string =
46 [] { static_assert(!is_same_template_v<PTR_TEMPLATE, PTR_TEMPLATE>,
"Bad array_size_string template argument"); };
49 constexpr
inline char array_size_string<std::weak_ptr>[] =
50 "Serialization Error: Array size in SST::Core::Serialization::weak_ptr() cannot fit inside size_t. size_t should " 51 "be used for array sizes.\n";
54 constexpr
inline char array_size_string<std::shared_ptr>[] =
55 "Serialization Error: Array size in SST::Core::Serialization::shared_ptr() cannot fit inside size_t. size_t should " 56 "be used for array sizes.\n";
58 template <
template <
class>
class PTR_TEMPLATE,
class PARENT_TYPE>
59 constexpr
auto wrapper_string =
60 [] { static_assert(!is_same_template_v<PTR_TEMPLATE, PTR_TEMPLATE>,
"Bad wrapper_string template arguments"); };
62 template <
class PARENT_TYPE>
63 constexpr
char wrapper_string<std::weak_ptr, PARENT_TYPE>[] =
64 "SST::Core::Serialization::weak_ptr(std::weak_ptr<PTR_TYPE>& ptr, std::shared_ptr<PARENT_TYPE>& parent)";
66 template <
class PARENT_ELEM_TYPE>
67 constexpr
char wrapper_string<std::weak_ptr, PARENT_ELEM_TYPE[]>[] =
68 "SST::Core::Serialization::weak_ptr(std::weak_ptr<PTR_TYPE>& ptr, std::shared_ptr<PARENT_TYPE>& parent, SIZE_T& " 71 template <
class PARENT_TYPE>
72 constexpr
char wrapper_string<std::shared_ptr, PARENT_TYPE>[] =
73 "SST::Core::Serialization::shared_ptr(std::shared_ptr<PTR_TYPE>& ptr, std::shared_ptr<PARENT_TYPE>& parent)";
75 template <
class PARENT_ELEM_TYPE>
76 constexpr
char wrapper_string<std::shared_ptr, PARENT_ELEM_TYPE[]>[] =
77 "SST::Core::Serialization::shared_ptr(std::shared_ptr<PTR_TYPE>& ptr, std::shared_ptr<PARENT_TYPE>& parent, " 82 template <
template <
class>
class PTR_TEMPLATE,
class PTR_TYPE>
83 std::pair<size_t, bool>
84 get_shared_ptr_owner_tag(
const PTR_TEMPLATE<PTR_TYPE>& ptr, serializer& ser)
87 if constexpr ( std::conjunction_v<is_same_template<PTR_TEMPLATE, std::weak_ptr>, std::is_array<PTR_TYPE>> ) {
89 std::weak_ptr<const void> weak_ptr = ptr.lock();
92 return get_shared_ptr_owner_tag(weak_ptr, ser);
95 if ( ser.mode() == serializer::SIZER )
96 return ser.sizer().get_shared_ptr_owner_tag(ptr);
98 return ser.packer().get_shared_ptr_owner_tag(ptr);
108 template <
template <
class>
class PTR_TEMPLATE,
class PTR_TYPE,
class PARENT_TYPE>
110 pack_shared_ptr_address(
111 const PTR_TEMPLATE<PTR_TYPE>& ptr,
const std::shared_ptr<PARENT_TYPE>& parent,
size_t* size, serializer& ser)
116 if constexpr ( is_same_template_v<PTR_TEMPLATE, std::shared_ptr> )
119 addr = ptr.lock().get();
122 bool nonnull = addr !=
nullptr;
123 ser.primitive(nonnull);
127 const void* parent_addr = parent.get();
130 Output::getDefaultObject().fatal(__LINE__, __FILE__, __func__, 1,
131 "Serialization Error: Serialized std::%s has a non-null stored pointer, but the parent specified by %s " 132 "has a null stored pointer.\nThere is no way to know how this raw pointer should be serialized.\n",
133 ptr_string<PTR_TEMPLATE>, wrapper_string<PTR_TEMPLATE, PARENT_TYPE>);
136 ptrdiff_t offset =
static_cast<const char*
>(addr) - static_cast<const char*>(parent_addr);
140 if constexpr ( is_unbounded_array_v<PARENT_TYPE> )
141 parent_size = *size *
sizeof(std::remove_extent_t<PARENT_TYPE>);
143 parent_size =
sizeof(PARENT_TYPE);
146 if ( offset < 0 || static_cast<size_t>(offset) > parent_size )
147 Output::getDefaultObject().fatal(__LINE__, __FILE__, __func__, 1,
148 "Serialization Error: Serialized std::%s has a stored pointer outside of the bounds of the parent " 149 "specified by %s.\nThere is no way to know how this raw pointer should be serialized.\n",
150 ptr_string<PTR_TEMPLATE>, wrapper_string<PTR_TEMPLATE, PARENT_TYPE>);
153 ser.primitive(offset);
159 template <
class PARENT_TYPE>
161 pack_shared_ptr_parent(
const std::shared_ptr<PARENT_TYPE>& parent,
size_t* size, serializer& ser, ser_opt_t opt)
164 using OWNER_TYPE = std::remove_cv_t<PARENT_TYPE>;
167 using ELEM_TYPE = std::remove_extent_t<OWNER_TYPE>;
170 OWNER_TYPE* parent_addr =
const_cast<OWNER_TYPE*
>(
reinterpret_cast<const OWNER_TYPE*
>(parent.get()));
173 bool nonnull = parent_addr !=
nullptr;
174 ser.primitive(nonnull);
178 if constexpr ( is_unbounded_array_v<OWNER_TYPE> ) {
182 ser.primitive(*size);
185 if constexpr ( is_trivially_serializable_v<ELEM_TYPE> )
186 ser.raw(parent_addr, *size *
sizeof(ELEM_TYPE));
188 serialize_array(ser, parent_addr, opt, *size, serialize_array_element<ELEM_TYPE>);
194 SST_SER(*parent_addr, opt);
201 template <
class PARENT_TYPE>
202 const std::shared_ptr<void>&
203 unpack_shared_ptr_owner(
size_t tag, std::shared_ptr<PARENT_TYPE>& parent,
size_t* size, serializer& ser, ser_opt_t opt)
206 using OWNER_TYPE = std::remove_cv_t<PARENT_TYPE>;
209 using ELEM_TYPE = std::remove_extent_t<OWNER_TYPE>;
213 auto&& [owner, is_new_tag] = ser.unpacker().get_shared_ptr_owner(tag);
218 static_assert(std::is_same_v<decltype(owner), std::shared_ptr<void>&>);
223 bool nonnull =
false;
224 ser.primitive(nonnull);
228 if constexpr ( is_unbounded_array_v<OWNER_TYPE> ) {
232 ser.primitive(*size);
236 if constexpr ( __cplusplus < 202002l )
237 owner = std::make_unique<OWNER_TYPE>(*size);
239 owner = std::make_shared<OWNER_TYPE>(*size);
242 if constexpr ( is_trivially_serializable_v<ELEM_TYPE> )
243 ser.raw(owner.get(), *size *
sizeof(ELEM_TYPE));
245 serialize_array(ser, owner.get(), opt, *size, serialize_array_element<ELEM_TYPE>);
251 if constexpr ( std::is_array_v<OWNER_TYPE> && __cplusplus < 202002l )
252 owner = std::shared_ptr<OWNER_TYPE>(
new ELEM_TYPE[std::extent_v<OWNER_TYPE>]());
254 owner = std::make_shared<OWNER_TYPE>();
257 SST_SER(*static_cast<OWNER_TYPE*>(owner.get()));
262 parent = std::static_pointer_cast<PARENT_TYPE>(owner);
284 template <
template <
class>
class PTR_TEMPLATE,
class PTR_TYPE,
class PARENT_TYPE>
285 void operator()(PTR_TEMPLATE<PTR_TYPE>& ptr, std::shared_ptr<PARENT_TYPE>& parent,
serializer& ser, ser_opt_t opt)
287 switch ( ser.mode() ) {
288 case serializer::SIZER:
289 case serializer::PACK:
292 auto owner_ne = [](
const auto& a,
const auto& b) {
return a.owner_before(b) || b.owner_before(a); };
295 if ( ptr.use_count() ? owner_ne(parent, ptr) : owner_ne(parent, PTR_TEMPLATE<PTR_TYPE>()) )
296 Output::getDefaultObject().fatal(__LINE__, __FILE__, __func__, 1,
297 "Serialization Error: Serialized std::%s does not have the same owning control block as the parent " 298 "specified by %s.\n",
299 ptr_string<PTR_TEMPLATE>, wrapper_string<PTR_TEMPLATE, PARENT_TYPE>);
303 auto [tag, is_new_tag] = get_shared_ptr_owner_tag(ptr, ser);
309 if ( tag != 0 ) pack_shared_ptr_address(ptr, parent, size, ser);
312 if ( is_new_tag ) pack_shared_ptr_parent(parent, size, ser, opt);
316 case serializer::UNPACK:
330 bool nonnull =
false;
331 ser.primitive(nonnull);
334 ptrdiff_t offset = 0;
335 if ( nonnull ) ser.primitive(offset);
338 const std::shared_ptr<void>& owner = unpack_shared_ptr_owner(tag, parent, size, ser, opt);
344 using ELEM_TYPE = std::remove_extent_t<PTR_TYPE>;
348 nonnull ?
reinterpret_cast<ELEM_TYPE*
>(
static_cast<char*
>(owner.get()) + offset) :
nullptr;
352 ptr = std::shared_ptr<PTR_TYPE>(owner, addr);
357 case serializer::MAP:
371 template <
class PTR_TYPE>
373 std::enable_if_t<!is_unbounded_array_v<PTR_TYPE> && !std::is_function_v<PTR_TYPE>>>
375 void operator()(std::shared_ptr<PTR_TYPE>& ptr,
serializer& ser, ser_opt_t opt)
377 ser_opt_t elem_opt = SerOption::is_set(opt, SerOption::as_ptr_elem) ? SerOption::as_ptr : SerOption::none;
382 SST_FRIEND_SERIALIZE();
388 template <
class PTR_TYPE>
390 std::enable_if_t<!is_unbounded_array_v<PTR_TYPE> && !std::is_function_v<PTR_TYPE>>>
392 void operator()(std::weak_ptr<PTR_TYPE>& ptr,
serializer& ser, ser_opt_t opt)
394 ser_opt_t elem_opt = SerOption::is_set(opt, SerOption::as_ptr_elem) ? SerOption::as_ptr : SerOption::none;
402 std::shared_ptr<PTR_TYPE> parent = ptr.lock();
405 SST_FRIEND_SERIALIZE();
430 template <
template <
class>
class PTR_TEMPLATE,
class PTR_TYPE,
class PARENT_TYPE = PTR_TYPE,
class SIZE_T = void,
431 class OWNER_TYPE = std::shared_ptr<PARENT_TYPE>&>
434 PTR_TEMPLATE<PTR_TYPE>& ptr;
439 template <
template <
class>
class PTR_TEMPLATE,
class PTR_TYPE,
class PARENT_ELEM_TYPE,
class SIZE_T,
class OWNER_TYPE>
442 PTR_TEMPLATE<PTR_TYPE>& ptr;
451 template <
template <
class>
class PTR_TEMPLATE,
class PTR_TYPE,
class PARENT_TYPE,
class SIZE_T,
class OWNER_TYPE>
452 class serialize_impl<pvt::shared_ptr_wrapper<PTR_TEMPLATE, PTR_TYPE, PARENT_TYPE, SIZE_T, OWNER_TYPE>,
453 std::enable_if_t<!std::is_function_v<PTR_TYPE>>>
458 ser_opt_t elem_opt = SerOption::is_set(opt, SerOption::as_ptr_elem) ? SerOption::as_ptr : SerOption::none;
459 if constexpr ( !is_unbounded_array_v<PARENT_TYPE> ) {
463 else if constexpr ( std::is_same_v<SIZE_T, size_t> ) {
469 const auto mode = ser.mode();
471 if ( mode != serializer::UNPACK ) size = get_array_size(ptr.size, pvt::array_size_string<PTR_TEMPLATE>);
473 if ( mode == serializer::UNPACK ) ptr.size =
static_cast<SIZE_T
>(size);
476 SST_FRIEND_SERIALIZE();
484 template <
class PTR_TYPE,
class PARENT_TYPE>
486 shared_ptr(std::shared_ptr<PTR_TYPE>& ptr, std::shared_ptr<PARENT_TYPE>& parent)
488 return { ptr, parent };
493 template <
class PTR_TYPE,
class SIZE_T>
494 std::enable_if_t<is_unbounded_array_v<PTR_TYPE>, pvt::shared_ptr_wrapper<std::shared_ptr, PTR_TYPE, PTR_TYPE, SIZE_T>>
495 shared_ptr(std::shared_ptr<PTR_TYPE>& ptr, SIZE_T& size)
497 return { ptr, ptr, size };
503 template <
class PTR_TYPE,
class PARENT_TYPE,
class SIZE_T>
504 std::enable_if_t<is_unbounded_array_v<PARENT_TYPE>,
505 pvt::shared_ptr_wrapper<std::shared_ptr, PTR_TYPE, PARENT_TYPE, SIZE_T>>
506 shared_ptr(std::shared_ptr<PTR_TYPE>& ptr, std::shared_ptr<PARENT_TYPE>& parent, SIZE_T& size)
508 return { ptr, parent, size };
512 template <
class PTR_TYPE>
513 std::shared_ptr<PTR_TYPE>&
514 shared_ptr(std::shared_ptr<PTR_TYPE>& ptr)
524 template <
class PTR_TYPE,
class PARENT_TYPE>
525 std::enable_if_t<!is_unbounded_array_v<PARENT_TYPE>, pvt::shared_ptr_wrapper<std::weak_ptr, PTR_TYPE, PARENT_TYPE>>
526 weak_ptr(std::weak_ptr<PTR_TYPE>& ptr, std::shared_ptr<PARENT_TYPE>& parent)
528 return { ptr, parent };
534 template <
class PTR_TYPE,
class SIZE_T>
535 std::enable_if_t<is_unbounded_array_v<PTR_TYPE>,
536 pvt::shared_ptr_wrapper<std::weak_ptr, PTR_TYPE, PTR_TYPE, SIZE_T, std::shared_ptr<PTR_TYPE>>>
537 weak_ptr(std::weak_ptr<PTR_TYPE>& ptr, SIZE_T& size)
539 return { ptr, ptr.lock(), size };
545 template <
class PTR_TYPE,
class PARENT_TYPE,
class SIZE_T>
546 std::enable_if_t<is_unbounded_array_v<PARENT_TYPE>,
547 pvt::shared_ptr_wrapper<std::weak_ptr, PTR_TYPE, PARENT_TYPE, SIZE_T>>
548 weak_ptr(std::weak_ptr<PTR_TYPE>& ptr, std::shared_ptr<PARENT_TYPE>& parent, SIZE_T& size)
550 return { ptr, parent, size };
554 template <
class PTR_TYPE>
555 std::weak_ptr<PTR_TYPE>&
556 weak_ptr(std::weak_ptr<PTR_TYPE>& ptr)
563 #endif // SST_CORE_SERIALIZATION_IMPL_SERIALIZE_SHARED_PTR_H This class is basically a wrapper for objects to declare the order in which their members should be s...
Definition: serializer.h:42
Definition: serialize_shared_ptr.h:432
Base serialize class.
Definition: serialize.h:113
Definition: serialize_shared_ptr.h:268