Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/sst/core/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ nobase_dist_sst_HEADERS = \
serialization/impl/serialize_insertable.h \
serialization/impl/serialize_optional.h \
serialization/impl/ser_shared_ptr_tracker.h \
serialization/impl/serialize_shared_ptr.h \
serialization/impl/serialize_tuple.h \
serialization/impl/serialize_unique_ptr.h \
serialization/impl/serialize_utility.h \
Expand Down Expand Up @@ -243,6 +244,7 @@ sst_core_sources = \
serialization/impl/mapper.cc \
serialization/impl/serialize_array.cc \
serialization/impl/serialize_trivial.cc \
serialization/impl/serialize_shared_ptr.cc \
sstinfo.h \
interfaces/TestEvent.cc \
interfaces/stdMem.cc \
Expand Down
20 changes: 12 additions & 8 deletions src/sst/core/serialization/impl/serialize_shared_ptr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,23 @@ template class serialize_impl<pvt::shared_ptr_wrapper<std::shared_ptr, int[], in
template class serialize_impl<pvt::shared_ptr_wrapper<std::shared_ptr, int[], int[], int>>;
template class serialize_impl<pvt::shared_ptr_wrapper<std::shared_ptr, int[], int[], size_t>>;
template class serialize_impl<pvt::shared_ptr_wrapper<std::shared_ptr, int[], size_t>>;
template class serialize_impl<pvt::shared_ptr_wrapper<std::shared_ptr, int, int[10], int>>;
template class serialize_impl<pvt::shared_ptr_wrapper<std::shared_ptr, int, int[10], size_t>>;
template class serialize_impl<pvt::shared_ptr_wrapper<std::shared_ptr, int[10], int>>;
template class serialize_impl<pvt::shared_ptr_wrapper<std::shared_ptr, int[10], int[10], int>>;
template class serialize_impl<pvt::shared_ptr_wrapper<std::shared_ptr, int[10], int[10], size_t>>;
template class serialize_impl<pvt::shared_ptr_wrapper<std::shared_ptr, int[10], size_t>>;

template class serialize_impl<pvt::shared_ptr_wrapper<std::weak_ptr, int, int>>;
template class serialize_impl<pvt::shared_ptr_wrapper<std::weak_ptr, int, size_t>>;

#if SST_SERIALIZE_WEAK_PTR_ARRAY
template class serialize_impl<pvt::shared_ptr_wrapper<std::weak_ptr, int, int[], int>>;
template class serialize_impl<pvt::shared_ptr_wrapper<std::weak_ptr, int, int[], size_t>>;
template class serialize_impl<pvt::shared_ptr_wrapper<std::weak_ptr, int, size_t>>;
template class serialize_impl<pvt::shared_ptr_wrapper<std::weak_ptr, int[], int[], int, std::shared_ptr<int[]>>>;
template class serialize_impl<pvt::shared_ptr_wrapper<std::weak_ptr, int[], int[], int>>;
template class serialize_impl<pvt::shared_ptr_wrapper<std::weak_ptr, int[], int[], size_t, std::shared_ptr<int[]>>>;
template class serialize_impl<pvt::shared_ptr_wrapper<std::weak_ptr, int[], int[], size_t>>;

template class serialize_impl<pvt::shared_ptr_wrapper<std::shared_ptr, int, int[10], int>>;
template class serialize_impl<pvt::shared_ptr_wrapper<std::shared_ptr, int, int[10], size_t>>;
template class serialize_impl<pvt::shared_ptr_wrapper<std::shared_ptr, int[10], int>>;
template class serialize_impl<pvt::shared_ptr_wrapper<std::shared_ptr, int[10], int[10], int>>;
template class serialize_impl<pvt::shared_ptr_wrapper<std::shared_ptr, int[10], int[10], size_t>>;
template class serialize_impl<pvt::shared_ptr_wrapper<std::shared_ptr, int[10], size_t>>;
template class serialize_impl<pvt::shared_ptr_wrapper<std::weak_ptr, int, int[10], int>>;
template class serialize_impl<pvt::shared_ptr_wrapper<std::weak_ptr, int, int[10], size_t>>;
template class serialize_impl<pvt::shared_ptr_wrapper<std::weak_ptr, int[10], int[10], int, std::shared_ptr<int[10]>>>;
Expand All @@ -51,4 +53,6 @@ template class serialize_impl<
pvt::shared_ptr_wrapper<std::weak_ptr, int[10], int[10], size_t, std::shared_ptr<int[10]>>>;
template class serialize_impl<pvt::shared_ptr_wrapper<std::weak_ptr, int[10], int[10], size_t>>;

#endif // SST_SERIALIZE_WEAK_PTR_ARRAY

} // namespace SST::Core::Serialization
42 changes: 39 additions & 3 deletions src/sst/core/serialization/impl/serialize_shared_ptr.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@
#ifndef SST_CORE_SERIALIZATION_IMPL_SERIALIZE_SHARED_PTR_H
#define SST_CORE_SERIALIZATION_IMPL_SERIALIZE_SHARED_PTR_H

// libc++ versions before 15 define std::weak_ptr<T>::element_type as T instead of std::remove_extent_t<T>, so we must
// disable serialization of std::weak_ptr arrays.
// https://reviews.llvm.org/D112092 https://cplusplus.github.io/LWG/issue3001
#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 150000
#define SST_SERIALIZE_WEAK_PTR_ARRAY 0
#else
#define SST_SERIALIZE_WEAK_PTR_ARRAY 1
#endif

#ifndef SST_INCLUDING_SERIALIZE_H
#warning \
"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"
Expand Down Expand Up @@ -83,15 +92,21 @@ template <template <class> class PTR_TEMPLATE, class PTR_TYPE>
std::pair<size_t, bool>
get_shared_ptr_owner_tag(const PTR_TEMPLATE<PTR_TYPE>& ptr, serializer& ser)
{

#if SST_SERIALIZE_WEAK_PTR_ARRAY
// Workaround for libstdc++ bug 120561 which prevents converting std::weak_ptr<array> to std::weak_ptr<const void>
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120561
if constexpr ( std::conjunction_v<is_same_template<PTR_TEMPLATE, std::weak_ptr>, std::is_array<PTR_TYPE>> ) {
// We set weak_ptr on a separate statement so that ptr's shared_ptr refcount is restored before return statement
std::weak_ptr<const void> weak_ptr = ptr.lock();

// Return this function using the newly cast std::weak_ptr<const void> instead of std::weak_ptr<array>
return get_shared_ptr_owner_tag(weak_ptr, ser);
}
else {
else
#endif // SST_SERIALIZE_WEAK_PTR_ARRAY

{
if ( ser.mode() == serializer::SIZER )
return ser.sizer().get_shared_ptr_owner_tag(ptr);
else
Expand Down Expand Up @@ -386,8 +401,13 @@ class serialize_impl<std::shared_ptr<PTR_TYPE>,
// For std::weak_ptr to unbounded arrays with runtime size, the wrapper function must be used.
// std::weak_ptr to functions is not supported.
template <class PTR_TYPE>
class serialize_impl<std::weak_ptr<PTR_TYPE>,
std::enable_if_t<!is_unbounded_array_v<PTR_TYPE> && !std::is_function_v<PTR_TYPE>>>
class serialize_impl<std::weak_ptr<PTR_TYPE>, std::enable_if_t<
#if SST_SERIALIZE_WEAK_PTR_ARRAY
!is_unbounded_array_v<PTR_TYPE>
#else
!std::is_array_v<PTR_TYPE>
#endif
&& !std::is_function_v<PTR_TYPE>>>
{
void operator()(std::weak_ptr<PTR_TYPE>& ptr, serializer& ser, ser_opt_t opt)
{
Expand Down Expand Up @@ -519,6 +539,8 @@ shared_ptr(std::shared_ptr<PTR_TYPE>& ptr)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// std::weak_ptr wrappers

#if SST_SERIALIZE_WEAK_PTR_ARRAY

// SST_SER( SST::Core::Serialization::weak_ptr( std::weak_ptr&, std::shared:ptr& ) ) serializes a std::weak_ptr with a
// parent std::shared_ptr managing the owned object.
template <class PTR_TYPE, class PARENT_TYPE>
Expand Down Expand Up @@ -550,6 +572,20 @@ weak_ptr(std::weak_ptr<PTR_TYPE>& ptr, std::shared_ptr<PARENT_TYPE>& parent, SIZ
return { ptr, parent, size };
}

#else // SST_SERIALIZE_WEAK_PTR_ARRAY

// SST_SER( SST::Core::Serialization::weak_ptr( std::weak_ptr&, std::shared:ptr& ) ) serializes a std::weak_ptr with a
// parent std::shared_ptr managing the owned object.
template <class PTR_TYPE, class PARENT_TYPE>
std::enable_if_t<!std::is_array_v<PARENT_TYPE>, pvt::shared_ptr_wrapper<std::weak_ptr, PTR_TYPE, PARENT_TYPE>>
weak_ptr(std::weak_ptr<PTR_TYPE>& ptr, std::shared_ptr<PARENT_TYPE>& parent)
{
return { ptr, parent };
}


#endif // SST_SERIALIZE_WEAK_PTR_ARRAY

// Identity operation for consistency -- SST_SER( SST::Core::Serialization::weak_ptr(ptr) ) is same as SST_SER(ptr).
template <class PTR_TYPE>
std::weak_ptr<PTR_TYPE>&
Expand Down
3 changes: 1 addition & 2 deletions src/sst/core/serialization/serialize.h
Original file line number Diff line number Diff line change
Expand Up @@ -425,8 +425,7 @@ sst_ser_or_helper(Args... args)
#include "sst/core/serialization/impl/serialize_bitset.h"
#include "sst/core/serialization/impl/serialize_insertable.h"
#include "sst/core/serialization/impl/serialize_optional.h"
// Disable until more stable across platforms
// #include "sst/core/serialization/impl/serialize_shared_ptr.h"
#include "sst/core/serialization/impl/serialize_shared_ptr.h"
#include "sst/core/serialization/impl/serialize_string.h"
#include "sst/core/serialization/impl/serialize_trivial.h"
#include "sst/core/serialization/impl/serialize_tuple.h"
Expand Down
55 changes: 30 additions & 25 deletions src/sst/core/testElements/coreTest_Serialization.cc
Original file line number Diff line number Diff line change
Expand Up @@ -757,7 +757,7 @@ checkSameOwner(const T1& t1, const T2& t2)
}

// Compare two std::shared_ptr
/*template <typename T>
template <typename T>
bool
checkSharedPtr(
const std::shared_ptr<T>& p1, const std::shared_ptr<T>& p2, size_t* p1_size = nullptr, size_t* p2_size = nullptr)
Expand All @@ -781,9 +781,9 @@ checkSharedPtr(
else
return objectEqual(*reinterpret_cast<T*>(p1.get()), *reinterpret_cast<T*>(p2.get()));
}
*/

// Compare two std::weak_ptr
/*template <typename T>
template <typename T>
bool
checkSharedPtr(
const std::weak_ptr<T>& p1, const std::weak_ptr<T>& p2, size_t* p1_size = nullptr, size_t* p2_size = nullptr)
Expand All @@ -800,9 +800,9 @@ checkSharedPtr(const std::tuple<T...>& p1, const std::tuple<T...>& p2)
[&](auto&&... p1s) { return std::apply([&](auto&&... p2s) { return (checkSharedPtr(p1s, p2s) && ...); }, p2); },
p1);
}
*/

// Test std::shared_ptr and std::weak_ptr
/*void
void
testSharedPtr(Output& output, const std::unique_ptr<SST::RNG::Random>& rng)
{
auto test = [&](auto value, auto rand) {
Expand Down Expand Up @@ -830,28 +830,33 @@ testSharedPtr(Output& output, const std::unique_ptr<SST::RNG::Random>& rng)
}
}

// a duplicated std::shared_ptr with a std::weak_ptr
#if !SST_SERIALIZE_WEAK_PTR_ARRAY
if constexpr ( !std::is_array_v<T> )
#endif
{
std::shared_ptr<T> in1 = std::make_shared<T>(rand()), in2 = in1;
std::weak_ptr<T> in3 = in2;
std::shared_ptr<T> out1 = std::make_shared<T>(rand()), out2 = std::make_shared<T>(rand());
std::weak_ptr<T> out3;

serializeDeserialize(std::tie(in1, in2, in3), std::tie(out1, out2, out3));
if ( !checkSameOwner(out1, out2) || !checkSameOwner(out2, out3) ||
!checkSharedPtr(std::tie(in1, in2, in3), std::tie(out1, out2, out3)) ) {
output.output("ERROR: shared_ptr did not serialize/deserialize properly (test 3)\n");
// a duplicated std::shared_ptr with a std::weak_ptr
{
std::shared_ptr<T> in1 = std::make_shared<T>(rand()), in2 = in1;
std::weak_ptr<T> in3 = in2;
std::shared_ptr<T> out1 = std::make_shared<T>(rand()), out2 = std::make_shared<T>(rand());
std::weak_ptr<T> out3;

serializeDeserialize(std::tie(in1, in2, in3), std::tie(out1, out2, out3));
if ( !checkSameOwner(out1, out2) || !checkSameOwner(out2, out3) ||
!checkSharedPtr(std::tie(in1, in2, in3), std::tie(out1, out2, out3)) ) {
output.output("ERROR: shared_ptr did not serialize/deserialize properly (test 3)\n");
}
}
}

// an expired std::weak_ptr
{
std::weak_ptr<T> in = std::make_shared<T>(rand());
std::weak_ptr<T> out;
// an expired std::weak_ptr
{
std::weak_ptr<T> in = std::make_shared<T>(rand());
std::weak_ptr<T> out;

serializeDeserialize(std::tie(in), std::tie(out));
if ( !checkSharedPtr(in, out) ) {
output.output("ERROR: shared_ptr did not serialize/deserialize properly (test 4)\n");
serializeDeserialize(std::tie(in), std::tie(out));
if ( !checkSharedPtr(in, out) ) {
output.output("ERROR: shared_ptr did not serialize/deserialize properly (test 4)\n");
}
}
}

Expand Down Expand Up @@ -955,7 +960,7 @@ testSharedPtr(Output& output, const std::unique_ptr<SST::RNG::Random>& rng)
return v;
});
}
*/

coreTestSerialization::coreTestSerialization(ComponentId_t id, Params& params) :
Component(id)
{
Expand Down Expand Up @@ -1028,7 +1033,7 @@ coreTestSerialization::coreTestSerialization(ComponentId_t id, Params& params) :
checkSimpleSerializeDeserialize<std::string*>::check_all("test_string", out, "std::string*");
}
else if ( test == "shared_ptr" ) {
// testSharedPtr(out, rng);
testSharedPtr(out, rng);
}
else if ( test == "array" ) {
{
Expand Down
4 changes: 2 additions & 2 deletions tests/testsuite_default_Serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ def test_Serialization_unique_ptr(self):
def test_Serialization_variant(self):
self.serialization_test_template("variant")

#def test_Serialization_shared_ptr(self):
# self.serialization_test_template("shared_ptr")
def test_Serialization_shared_ptr(self):
self.serialization_test_template("shared_ptr")

def test_Serialization_aggregate(self):
self.serialization_test_template("aggregate")
Expand Down
Loading