From 14b38c44275c605c7565a63a32c22a711032c539 Mon Sep 17 00:00:00 2001 From: Scott Hemmert Date: Wed, 12 Jun 2024 15:52:48 -0600 Subject: [PATCH] Base comp ser (#1089) * Added serializable_base as the base serializable class. Serializable and BaseComponent now inherit from serializable_base. This allows different serialize_impl<> templates for serializable and BaseComponent, giving more control over Component serialization. * Fixed bug for --run-mode=init. Fixes #1087. * Made serialization tests run with --run-mode=init since they test everything during the construct phase. This will test that --run-mode=init operates correctly. * Added [[maybe_unused]] to __Eli_Derived_Level at suggestion of @ldalessa --- src/sst/core/CMakeLists.txt | 2 +- src/sst/core/Makefile.am | 3 +- src/sst/core/baseComponent.cc | 49 +++- src/sst/core/baseComponent.h | 36 ++- src/sst/core/eli/elementinfo.h | 17 +- src/sst/core/main.cc | 32 +- src/sst/core/serialization/CMakeLists.txt | 1 + src/sst/core/serialization/serializable.h | 240 +-------------- .../{serializable.cc => serializable_base.cc} | 6 +- .../core/serialization/serializable_base.h | 275 ++++++++++++++++++ .../serialization/serialize_serializable.cc | 17 +- .../serialization/serialize_serializable.h | 49 +--- .../test_Serialization_componentinfo.out | 2 +- tests/refFiles/test_Serialization_default.out | 2 +- tests/refFiles/test_Serialization_handler.out | 2 +- tests/testsuite_default_Serialization.py | 2 +- 16 files changed, 409 insertions(+), 326 deletions(-) rename src/sst/core/serialization/{serializable.cc => serializable_base.cc} (93%) create mode 100644 src/sst/core/serialization/serializable_base.h diff --git a/src/sst/core/CMakeLists.txt b/src/sst/core/CMakeLists.txt index 229f7e950..dce8e2810 100644 --- a/src/sst/core/CMakeLists.txt +++ b/src/sst/core/CMakeLists.txt @@ -81,7 +81,7 @@ add_library( profile/eventHandlerProfileTool.cc profile/syncProfileTool.cc profile/profiletool.cc - serialization/serializable.cc + serialization/serializable_base.cc serialization/serialize_serializable.cc serialization/serializer.cc serialization/statics.cc diff --git a/src/sst/core/Makefile.am b/src/sst/core/Makefile.am index 2cb8abb85..fbf00c7d5 100644 --- a/src/sst/core/Makefile.am +++ b/src/sst/core/Makefile.am @@ -88,6 +88,7 @@ nobase_dist_sst_HEADERS = \ eli/statsInfo.h \ eli/subcompSlotInfo.h \ serialization/serializable.h \ + serialization/serializable_base.h \ serialization/serializable_fwd.h \ serialization/serialize.h \ serialization/serialize_impl_fwd.h \ @@ -210,7 +211,7 @@ sst_core_sources = \ ssthandler.cc \ sstpart.cc \ timeVortex.cc \ - serialization/serializable.cc \ + serialization/serializable_base.cc \ serialization/serialize_serializable.cc \ serialization/serializer.cc \ serialization/statics.cc \ diff --git a/src/sst/core/baseComponent.cc b/src/sst/core/baseComponent.cc index b94580a49..1c3680443 100644 --- a/src/sst/core/baseComponent.cc +++ b/src/sst/core/baseComponent.cc @@ -33,10 +33,10 @@ namespace SST { -BaseComponent::BaseComponent() : SST::Core::Serialization::serializable() {} +BaseComponent::BaseComponent() : SST::Core::Serialization::serializable_base() {} BaseComponent::BaseComponent(ComponentId_t id) : - SST::Core::Serialization::serializable(), + SST::Core::Serialization::serializable_base(), my_info(Simulation_impl::getSimulation()->getComponentInfo(id)), sim_(Simulation_impl::getSimulation()), isExtension(false) @@ -856,5 +856,50 @@ BaseComponent::serialize_order(SST::Core::Serialization::serializer& ser) } } +namespace Core { +namespace Serialization { +namespace pvt { + +static const long null_ptr_id = -1; + +void +size_basecomponent(serializable_base* s, serializer& ser) +{ + long dummy = 0; + ser.size(dummy); + if ( s ) { s->serialize_order(ser); } +} + +void +pack_basecomponent(serializable_base* s, serializer& ser) +{ + if ( s ) { + long cls_id = s->cls_id(); + ser.pack(cls_id); + s->serialize_order(ser); + } + else { + long id = null_ptr_id; + ser.pack(id); + } +} + +void +unpack_basecomponent(serializable_base*& s, serializer& ser) +{ + long cls_id; + ser.unpack(cls_id); + if ( cls_id == null_ptr_id ) { s = nullptr; } + else { + s = SST::Core::Serialization::serializable_factory::get_serializable(cls_id); + ser.report_new_pointer(reinterpret_cast(s)); + s->serialize_order(ser); + } +} + +} // namespace pvt +} // namespace Serialization +} // namespace Core + } // namespace SST diff --git a/src/sst/core/baseComponent.h b/src/sst/core/baseComponent.h index 5f38d0467..67384dd9a 100644 --- a/src/sst/core/baseComponent.h +++ b/src/sst/core/baseComponent.h @@ -19,6 +19,7 @@ #include "sst/core/factory.h" #include "sst/core/oneshot.h" #include "sst/core/profile/componentProfileTool.h" +#include "sst/core/serialization/serializable_base.h" #include "sst/core/sst_types.h" #include "sst/core/statapi/statbase.h" #include "sst/core/statapi/statengine.h" @@ -48,7 +49,7 @@ class UnitAlgebra; /** * Main component object for the simulation. */ -class BaseComponent : public SST::Core::Serialization::serializable +class BaseComponent : public SST::Core::Serialization::serializable_base { friend class Component; @@ -1120,6 +1121,39 @@ class serialize_impl*> } }; + +namespace pvt { + +void size_basecomponent(serializable_base* s, serializer& ser); + +void pack_basecomponent(serializable_base* s, serializer& ser); + +void unpack_basecomponent(serializable_base*& s, serializer& ser); +} // namespace pvt + +template +class serialize_impl::value>::type> +{ + template + friend class serialize; + void operator()(T*& s, serializer& ser) + { + serializable_base* sp = static_cast(s); + switch ( ser.mode() ) { + case serializer::SIZER: + pvt::size_basecomponent(sp, ser); + break; + case serializer::PACK: + pvt::pack_basecomponent(sp, ser); + break; + case serializer::UNPACK: + pvt::unpack_basecomponent(sp, ser); + break; + } + s = static_cast(sp); + } +}; + } // namespace Serialization } // namespace Core diff --git a/src/sst/core/eli/elementinfo.h b/src/sst/core/eli/elementinfo.h index 8ce1da548..aa927d872 100644 --- a/src/sst/core/eli/elementinfo.h +++ b/src/sst/core/eli/elementinfo.h @@ -405,14 +405,15 @@ SST_ELI_getTertiaryNumberFromVersion(SST_ELI_element_version_extraction ver) // this class. Sny local information will overwrite any inherited // information. See comment for SST_ELI_DECLARE_BASE in elibase.h for // info on how __EliDerivedLevel is used. -#define SST_ELI_REGISTER_DERIVED(base, cls, lib, name, version, desc) \ - static constexpr int __EliDerivedLevel = std::is_same::value ? __EliBaseLevel : __EliBaseLevel + 1; \ - static bool ELI_isLoaded() \ - { \ - return SST::ELI::InstantiateBuilder::isLoaded() && \ - SST::ELI::InstantiateBuilderInfo::isLoaded(); \ - } \ - SST_ELI_FORCE_INSTANTIATION(base, cls) \ +#define SST_ELI_REGISTER_DERIVED(base, cls, lib, name, version, desc) \ + [[maybe_unused]] static constexpr int __EliDerivedLevel = \ + std::is_same::value ? __EliBaseLevel : __EliBaseLevel + 1; \ + static bool ELI_isLoaded() \ + { \ + return SST::ELI::InstantiateBuilder::isLoaded() && \ + SST::ELI::InstantiateBuilderInfo::isLoaded(); \ + } \ + SST_ELI_FORCE_INSTANTIATION(base, cls) \ SST_ELI_DEFAULT_INFO(lib, name, ELI_FORWARD_AS_ONE(version), desc) #define SST_ELI_REGISTER_EXTERN(base, cls) \ diff --git a/src/sst/core/main.cc b/src/sst/core/main.cc index 860d9cad4..d900854c2 100644 --- a/src/sst/core/main.cc +++ b/src/sst/core/main.cc @@ -626,25 +626,27 @@ start_simulation(uint32_t tid, SimThreadInfo_t& info, Core::ThreadSafe::Barrier& sim->restart(info.config); } /* Run Simulation */ - sim->run(); - barrier.wait(); + if ( info.config->runMode() == SimulationRunMode::RUN || info.config->runMode() == SimulationRunMode::BOTH ) { + sim->run(); + barrier.wait(); - /* Adjust clocks at simulation end to - * reflect actual simulation end if that - * differs from detected simulation end - */ - sim->adjustTimeAtSimEnd(); - barrier.wait(); + /* Adjust clocks at simulation end to + * reflect actual simulation end if that + * differs from detected simulation end + */ + sim->adjustTimeAtSimEnd(); + barrier.wait(); - sim->complete(); - barrier.wait(); + sim->complete(); + barrier.wait(); - sim->finish(); - barrier.wait(); + sim->finish(); + barrier.wait(); - /* Tell stat outputs simulation is done */ - do_statoutput_end_simulation(info.myRank); - barrier.wait(); + /* Tell stat outputs simulation is done */ + do_statoutput_end_simulation(info.myRank); + barrier.wait(); + } info.simulated_time = sim->getEndSimTime(); // g_output.output(CALL_INFO,"Simulation time = %s\n",info.simulated_time.toStringBestSI().c_str()); diff --git a/src/sst/core/serialization/CMakeLists.txt b/src/sst/core/serialization/CMakeLists.txt index 992a20c17..1f7759f57 100644 --- a/src/sst/core/serialization/CMakeLists.txt +++ b/src/sst/core/serialization/CMakeLists.txt @@ -16,6 +16,7 @@ set(SSTSerializationHeaders serializable_fwd.h + serializable_base.h serializable.h serialize_array.h serialize_atomic.h diff --git a/src/sst/core/serialization/serializable.h b/src/sst/core/serialization/serializable.h index ad8c247ad..4cdcbb9df 100644 --- a/src/sst/core/serialization/serializable.h +++ b/src/sst/core/serialization/serializable.h @@ -12,261 +12,33 @@ #ifndef SST_CORE_SERIALIZATION_SERIALIZABLE_H #define SST_CORE_SERIALIZATION_SERIALIZABLE_H -#include "sst/core/serialization/serializer.h" -#include "sst/core/warnmacros.h" +#include "sst/core/serialization/serializable_base.h" -#include -#include -#include -#include namespace SST { namespace Core { namespace Serialization { -namespace pvt { -// Functions to implement the hash for cls_id at compile time. The -// hash function being implemented is: - -inline uint32_t -type_hash(const char* key) -{ - int len = ::strlen(key); - uint32_t hash = 0; - for ( int i = 0; i < len; ++i ) { - hash += key[i]; - hash += (hash << 10); - hash ^= (hash >> 6); - } - hash += (hash << 3); - hash ^= (hash >> 11); - hash += (hash << 15); - - return hash; -} - -// Using constexpr is very limited, so the implementation is a bit -// convoluted. May be able to streamline later. - -// computes hash ^= (hash >> 6) -constexpr uint32_t -B(const uint32_t b) -{ - return b ^ (b >> 6); -} - -// computes hash += (hash << 10) -constexpr uint32_t -A(const uint32_t a) -{ - return B((a << 10) + a); -} - -// recursive piece that computes the for loop -template -constexpr uint32_t -ct_hash_rec(const char* str) -{ - return A(str[idx] + ct_hash_rec(str)); -} - -// End of the recursion (i.e. when you've walked back off the front of -// the string -template <> -constexpr uint32_t -ct_hash_rec(const char* UNUSED(str)) -{ - return 0; -} - -// computes hash += (hash << 15) -constexpr uint32_t -E(const uint32_t e) -{ - return (e << 15) + e; -} - -// computes hash ^= (hash >> 11) -constexpr uint32_t -D(const uint32_t d) -{ - return E((d >> 11) ^ d); -} - -// computes hash += (hash << 3) -constexpr uint32_t -C(const uint32_t c) -{ - return D((c << 3) + c); -} - -// Main function that computes the final manipulations after calling -// the recursive function to compute the for loop. -template -constexpr uint32_t -ct_hash(const char* str) -{ - return C(ct_hash_rec(str)); -} - -// Macro that should be used to call the compile time hash function -#define COMPILE_TIME_HASH(x) (::SST::Core::Serialization::pvt::ct_hash(x)) - -} // namespace pvt - -class serializable +class serializable : public serializable_base { public: static constexpr uint32_t NullClsId = std::numeric_limits::max(); - virtual const char* cls_name() const = 0; + // virtual const char* cls_name() const = 0; - virtual void serialize_order(serializer& ser) = 0; + // virtual void serialize_order(serializer& ser) = 0; - virtual uint32_t cls_id() const = 0; - virtual std::string serialization_name() const = 0; + // virtual uint32_t cls_id() const = 0; + // virtual std::string serialization_name() const = 0; virtual ~serializable() {} - -protected: - typedef enum { ConstructorFlag } cxn_flag_t; - static void serializable_abort(uint32_t line, const char* file, const char* func, const char* obj); -}; - -template -class serializable_type -{}; - -#define ImplementVirtualSerializable(obj) \ -public: \ - virtual const char* cls_name() const override { return #obj; } - -#define NotSerializable(obj) \ -public: \ - static void throw_exc() { ::SST::Core::Serialization::serializable::serializable_abort(CALL_INFO_LONG, #obj); } \ - virtual void serialize_order(SST::Core::Serialization::serializer& UNUSED(sst)) override { throw_exc(); } \ - virtual uint32_t cls_id() const override \ - { \ - throw_exc(); \ - return ::SST::Core::Serialization::serializable::NullClsId; \ - } \ - static obj* construct_deserialize_stub() \ - { \ - throw_exc(); \ - return 0; \ - } \ - virtual std::string serialization_name() const override \ - { \ - throw_exc(); \ - return ""; \ - } \ - virtual const char* cls_name() const override { return #obj; } - -// virtual const char* cls_name() const override { return obj_str; } -#define ImplementSerializableDefaultConstructor(obj, obj_str) \ -public: \ - virtual const char* cls_name() const override \ - { \ - return SST::Core::Serialization::serializable_builder_impl::static_name(); \ - } \ - virtual uint32_t cls_id() const override \ - { \ - return SST::Core::Serialization::serializable_builder_impl::static_cls_id(); \ - } \ - static obj* construct_deserialize_stub() { return new obj; } \ - virtual std::string serialization_name() const override { return obj_str; } \ - \ -private: \ - friend class SST::Core::Serialization::serializable_builder_impl; \ - static bool you_forgot_to_add_ImplementSerializable_to_this_class() { return false; } - -#define SER_FORWARD_AS_ONE(...) __VA_ARGS__ - -#define ImplementSerializable(...) \ -public: \ - ImplementSerializableDefaultConstructor(SER_FORWARD_AS_ONE(__VA_ARGS__), #__VA_ARGS__) - -class serializable_builder -{ -public: - virtual serializable* build() const = 0; - - virtual ~serializable_builder() {} - - virtual const char* name() const = 0; - - virtual uint32_t cls_id() const = 0; - - virtual bool sanity(serializable* ser) = 0; }; -template -class serializable_builder_impl : public serializable_builder -{ -protected: - static const char* name_; - static const uint32_t cls_id_; - -public: - serializable* build() const override { return T::construct_deserialize_stub(); } - - const char* name() const override { return name_; } - - uint32_t cls_id() const override { return cls_id_; } - - static uint32_t static_cls_id() { return cls_id_; } - - static const char* static_name() { return name_; } - - bool sanity(serializable* ser) override { return (typeid(T) == typeid(*ser)); } -}; - -class serializable_factory -{ -protected: - typedef std::unordered_map builder_map; - static builder_map* builders_; - -public: - static serializable* get_serializable(uint32_t cls_id); - - /** - @return The cls id for the given builder - */ - static uint32_t - // add_builder(serializable_builder* builder, uint32_t cls_id); - add_builder(serializable_builder* builder, const char* name); - - static bool sanity(serializable* ser, uint32_t cls_id) { return (*builders_)[cls_id]->sanity(ser); } - - static void delete_statics(); -}; - -template -const char* serializable_builder_impl::name_ = typeid(T).name(); -template -const uint32_t serializable_builder_impl::cls_id_ = - serializable_factory::add_builder(new serializable_builder_impl, typeid(T).name()); - -// Hold off on trivially_serializable for now, as it's not really safe -// in the case of inheritance -// -// class trivially_serializable { -// }; - } // namespace Serialization } // namespace Core } // namespace SST -#define SerializableName(obj) #obj - -#define DeclareSerializable(obj) - -// Serialization macros for checkpoint/debug serialization -#define SST_SER(obj) ser& obj; -#define SST_SER_AS_PTR(obj) ser | obj; - #include "sst/core/serialization/serialize_serializable.h" #endif diff --git a/src/sst/core/serialization/serializable.cc b/src/sst/core/serialization/serializable_base.cc similarity index 93% rename from src/sst/core/serialization/serializable.cc rename to src/sst/core/serialization/serializable_base.cc index 321ee0768..f70dbc8ff 100644 --- a/src/sst/core/serialization/serializable.cc +++ b/src/sst/core/serialization/serializable_base.cc @@ -12,7 +12,7 @@ #include "sst_config.h" -#include "sst/core/serialization/serializable.h" +#include "sst/core/serialization/serializable_base.h" #include "sst/core/output.h" #include "sst/core/serialization/statics.h" @@ -28,7 +28,7 @@ static need_delete_statics del_statics; serializable_factory::builder_map* serializable_factory::builders_ = nullptr; void -serializable::serializable_abort(uint32_t line, const char* file, const char* func, const char* obj) +serializable_base::serializable_abort(uint32_t line, const char* file, const char* func, const char* obj) { SST::Output ser_abort("", 5, SST::Output::PrintAll, SST::Output::STDERR); ser_abort.fatal(line, file, func, 1, "ERROR: type %s should not be serialized\n", obj); @@ -73,7 +73,7 @@ serializable_factory::delete_statics() delete builders_; } -serializable* +serializable_base* serializable_factory::get_serializable(uint32_t cls_id) { builder_map::const_iterator it = builders_->find(cls_id); diff --git a/src/sst/core/serialization/serializable_base.h b/src/sst/core/serialization/serializable_base.h new file mode 100644 index 000000000..b04fb0d4e --- /dev/null +++ b/src/sst/core/serialization/serializable_base.h @@ -0,0 +1,275 @@ +// Copyright 2009-2024 NTESS. Under the terms +// of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Copyright (c) 2009-2024, NTESS +// All rights reserved. +// +// This file is part of the SST software package. For license +// information, see the LICENSE file in the top level directory of the +// distribution. + +#ifndef SST_CORE_SERIALIZATION_SERIALIZABLE_BASE_H +#define SST_CORE_SERIALIZATION_SERIALIZABLE_BASE_H + +#include "sst/core/serialization/serializer.h" +#include "sst/core/warnmacros.h" + +#include +#include +#include +#include + +namespace SST { +namespace Core { +namespace Serialization { + +namespace pvt { + +// Functions to implement the hash for cls_id at compile time. The +// hash function being implemented is: + +inline uint32_t +type_hash(const char* key) +{ + int len = ::strlen(key); + uint32_t hash = 0; + for ( int i = 0; i < len; ++i ) { + hash += key[i]; + hash += (hash << 10); + hash ^= (hash >> 6); + } + hash += (hash << 3); + hash ^= (hash >> 11); + hash += (hash << 15); + + return hash; +} + +// Using constexpr is very limited, so the implementation is a bit +// convoluted. May be able to streamline later. + +// computes hash ^= (hash >> 6) +constexpr uint32_t +B(const uint32_t b) +{ + return b ^ (b >> 6); +} + +// computes hash += (hash << 10) +constexpr uint32_t +A(const uint32_t a) +{ + return B((a << 10) + a); +} + +// recursive piece that computes the for loop +template +constexpr uint32_t +ct_hash_rec(const char* str) +{ + return A(str[idx] + ct_hash_rec(str)); +} + +// End of the recursion (i.e. when you've walked back off the front of +// the string +template <> +constexpr uint32_t +ct_hash_rec(const char* UNUSED(str)) +{ + return 0; +} + +// computes hash += (hash << 15) +constexpr uint32_t +E(const uint32_t e) +{ + return (e << 15) + e; +} + +// computes hash ^= (hash >> 11) +constexpr uint32_t +D(const uint32_t d) +{ + return E((d >> 11) ^ d); +} + +// computes hash += (hash << 3) +constexpr uint32_t +C(const uint32_t c) +{ + return D((c << 3) + c); +} + +// Main function that computes the final manipulations after calling +// the recursive function to compute the for loop. +template +constexpr uint32_t +ct_hash(const char* str) +{ + return C(ct_hash_rec(str)); +} + +// Macro that should be used to call the compile time hash function +#define COMPILE_TIME_HASH(x) (::SST::Core::Serialization::pvt::ct_hash(x)) + +} // namespace pvt + +class serializable_base +{ +public: + static constexpr uint32_t NullClsId = std::numeric_limits::max(); + + virtual const char* cls_name() const = 0; + + virtual void serialize_order(serializer& ser) = 0; + + virtual uint32_t cls_id() const = 0; + virtual std::string serialization_name() const = 0; + + virtual ~serializable_base() {} + +protected: + typedef enum { ConstructorFlag } cxn_flag_t; + static void serializable_abort(uint32_t line, const char* file, const char* func, const char* obj); +}; + +template +class serializable_type +{}; + +#define ImplementVirtualSerializable(obj) \ +public: \ + virtual const char* cls_name() const override { return #obj; } + +#define NotSerializable(obj) \ +public: \ + static void throw_exc() \ + { \ + ::SST::Core::Serialization::serializable_base::serializable_abort(CALL_INFO_LONG, #obj); \ + } \ + virtual void serialize_order(SST::Core::Serialization::serializer& UNUSED(sst)) override { throw_exc(); } \ + virtual uint32_t cls_id() const override \ + { \ + throw_exc(); \ + return ::SST::Core::Serialization::serializable_base::NullClsId; \ + } \ + static obj* construct_deserialize_stub() \ + { \ + throw_exc(); \ + return 0; \ + } \ + virtual std::string serialization_name() const override \ + { \ + throw_exc(); \ + return ""; \ + } \ + virtual const char* cls_name() const override { return #obj; } + +// virtual const char* cls_name() const override { return obj_str; } +#define ImplementSerializableDefaultConstructor(obj, obj_str) \ +public: \ + virtual const char* cls_name() const override \ + { \ + return SST::Core::Serialization::serializable_builder_impl::static_name(); \ + } \ + virtual uint32_t cls_id() const override \ + { \ + return SST::Core::Serialization::serializable_builder_impl::static_cls_id(); \ + } \ + static obj* construct_deserialize_stub() { return new obj; } \ + virtual std::string serialization_name() const override { return obj_str; } \ + \ +private: \ + friend class SST::Core::Serialization::serializable_builder_impl; \ + static bool you_forgot_to_add_ImplementSerializable_to_this_class() { return false; } + +#define SER_FORWARD_AS_ONE(...) __VA_ARGS__ + +#define ImplementSerializable(...) \ +public: \ + ImplementSerializableDefaultConstructor(SER_FORWARD_AS_ONE(__VA_ARGS__), #__VA_ARGS__) + +class serializable_builder +{ +public: + virtual serializable_base* build() const = 0; + + virtual ~serializable_builder() {} + + virtual const char* name() const = 0; + + virtual uint32_t cls_id() const = 0; + + virtual bool sanity(serializable_base* ser) = 0; +}; + +template +class serializable_builder_impl : public serializable_builder +{ +protected: + static const char* name_; + static const uint32_t cls_id_; + +public: + serializable_base* build() const override { return T::construct_deserialize_stub(); } + + const char* name() const override { return name_; } + + uint32_t cls_id() const override { return cls_id_; } + + static uint32_t static_cls_id() { return cls_id_; } + + static const char* static_name() { return name_; } + + bool sanity(serializable_base* ser) override { return (typeid(T) == typeid(*ser)); } +}; + +class serializable_factory +{ +protected: + typedef std::unordered_map builder_map; + static builder_map* builders_; + +public: + static serializable_base* get_serializable(uint32_t cls_id); + + /** + @return The cls id for the given builder + */ + static uint32_t + // add_builder(serializable_builder* builder, uint32_t cls_id); + add_builder(serializable_builder* builder, const char* name); + + static bool sanity(serializable_base* ser, uint32_t cls_id) { return (*builders_)[cls_id]->sanity(ser); } + + static void delete_statics(); +}; + +template +const char* serializable_builder_impl::name_ = typeid(T).name(); +template +const uint32_t serializable_builder_impl::cls_id_ = + serializable_factory::add_builder(new serializable_builder_impl, typeid(T).name()); + +// Hold off on trivially_serializable for now, as it's not really safe +// in the case of inheritance +// +// class trivially_serializable { +// }; + +} // namespace Serialization +} // namespace Core +} // namespace SST + +#define SerializableName(obj) #obj + +#define DeclareSerializable(obj) + +// Serialization macros for checkpoint/debug serialization +#define SST_SER(obj) ser& obj; +#define SST_SER_AS_PTR(obj) ser | obj; + +//#include "sst/core/serialization/serialize_serializable_base.h" + +#endif diff --git a/src/sst/core/serialization/serialize_serializable.cc b/src/sst/core/serialization/serialize_serializable.cc index 275bc21e9..da9d17abf 100644 --- a/src/sst/core/serialization/serialize_serializable.cc +++ b/src/sst/core/serialization/serialize_serializable.cc @@ -23,7 +23,7 @@ namespace pvt { static const long null_ptr_id = -1; void -size_serializable(serializable* s, serializer& ser) +size_serializable(serializable_base* s, serializer& ser) { long dummy = 0; ser.size(dummy); @@ -31,38 +31,29 @@ size_serializable(serializable* s, serializer& ser) } void -pack_serializable(serializable* s, serializer& ser) +pack_serializable(serializable_base* s, serializer& ser) { if ( s ) { - // debug_printf(dbg::serialize, - // "object with class id %ld: %s", - // s->cls_id(), s->cls_name()); long cls_id = s->cls_id(); ser.pack(cls_id); s->serialize_order(ser); } else { - // debug_printf(dbg::serialize, "null object"); long id = null_ptr_id; ser.pack(id); } } void -unpack_serializable(serializable*& s, serializer& ser) +unpack_serializable(serializable_base*& s, serializer& ser) { long cls_id; ser.unpack(cls_id); - if ( cls_id == null_ptr_id ) { - // debug_printf(dbg::serialize, "null pointer object"); - s = nullptr; - } + if ( cls_id == null_ptr_id ) { s = nullptr; } else { - // debug_printf(dbg::serialize, "unpacking class id %ld", cls_id); s = SST::Core::Serialization::serializable_factory::get_serializable(cls_id); ser.report_new_pointer(reinterpret_cast(s)); s->serialize_order(ser); - // debug_printf(dbg::serialize, "unpacked object %s", s->cls_name()); } } diff --git a/src/sst/core/serialization/serialize_serializable.h b/src/sst/core/serialization/serialize_serializable.h index 238a542e5..d2c8d50c8 100644 --- a/src/sst/core/serialization/serialize_serializable.h +++ b/src/sst/core/serialization/serialize_serializable.h @@ -24,42 +24,14 @@ namespace Serialization { namespace pvt { -void size_serializable(serializable* s, serializer& ser); +void size_serializable(serializable_base* s, serializer& ser); -void pack_serializable(serializable* s, serializer& ser); +void pack_serializable(serializable_base* s, serializer& ser); -void unpack_serializable(serializable*& s, serializer& ser); - - -void size_pointer(serializable* s, serializer& ser); - -void pack_pointer(serializable* s, serializer& ser); - -void unpack_pointer(serializable*& s, serializer& ser); +void unpack_serializable(serializable_base*& s, serializer& ser); } // namespace pvt -template <> -class serialize_impl -{ - - template - friend class serialize; - void operator()(serializable*& s, serializer& ser) - { - switch ( ser.mode() ) { - case serializer::SIZER: - pvt::size_serializable(s, ser); - break; - case serializer::PACK: - pvt::pack_serializable(s, ser); - break; - case serializer::UNPACK: - pvt::unpack_serializable(s, ser); - break; - } - } -}; template class serialize_impl< @@ -70,7 +42,7 @@ class serialize_impl< friend class serialize; void operator()(T*& s, serializer& ser) { - serializable* sp = static_cast(s); + serializable_base* sp = static_cast(s); switch ( ser.mode() ) { case serializer::SIZER: pvt::size_serializable(sp, ser); @@ -90,7 +62,7 @@ template void serialize_intrusive_ptr(T*& t, serializer& ser) { - serializable* s = t; + serializable_base* s = t; switch ( ser.mode() ) { case serializer::SIZER: pvt::size_serializable(s, ser); @@ -119,17 +91,6 @@ class serialize_impl< } }; -// Hold off on trivially_serializable for now, as it's not really safe -// in the case of inheritance -// -// template -// class serialize ::value>::type> { public: -// inline void operator()(T& t, serializer& ser){ -// ser.primitive(t); -// } -// }; - } // namespace Serialization } // namespace Core } // namespace SST diff --git a/tests/refFiles/test_Serialization_componentinfo.out b/tests/refFiles/test_Serialization_componentinfo.out index e11b3fec0..79cc4a1e5 100644 --- a/tests/refFiles/test_Serialization_componentinfo.out +++ b/tests/refFiles/test_Serialization_componentinfo.out @@ -9,4 +9,4 @@ id = 0, name = top_component, slot_name = NONE, defaultTimeBase = 500 id = 2, name = subcomp1_0, slot_name = slot0, defaultTimeBase = 1000, parent_id = 1 id = 3, name = subcomp1_1, slot_name = slot1, defaultTimeBase = 2000, parent_id = 1 id = 4, name = subcomp0_1, slot_name = slot1, parent_id = 0 -Simulation is complete, simulated time: 1 us +Simulation is complete, simulated time: 0 s diff --git a/tests/refFiles/test_Serialization_default.out b/tests/refFiles/test_Serialization_default.out index ab9670de7..79abf3396 100644 --- a/tests/refFiles/test_Serialization_default.out +++ b/tests/refFiles/test_Serialization_default.out @@ -1,2 +1,2 @@ WARNING: Building component "Component0" with no links assigned. -Simulation is complete, simulated time: 1 us +Simulation is complete, simulated time: 0 s diff --git a/tests/refFiles/test_Serialization_handler.out b/tests/refFiles/test_Serialization_handler.out index a15decbe1..e4d9693c7 100644 --- a/tests/refFiles/test_Serialization_handler.out +++ b/tests/refFiles/test_Serialization_handler.out @@ -63,4 +63,4 @@ metadata value: 8.9 internal value: 73 parameter value: 17 metadata value: 8.9 -Simulation is complete, simulated time: 1 us +Simulation is complete, simulated time: 0 s diff --git a/tests/testsuite_default_Serialization.py b/tests/testsuite_default_Serialization.py index 9d40bd3e6..094386a9a 100644 --- a/tests/testsuite_default_Serialization.py +++ b/tests/testsuite_default_Serialization.py @@ -91,7 +91,7 @@ def serialization_test_template(self, testtype, default_reffile = True): outfile = "{0}/test_Serialization_{1}.out".format(outdir,testtype) - options = "--model-options=\"{0}\"".format(testtype) + options = "--run-mode=init --model-options=\"{0}\"".format(testtype) # Force serial run since the serialization is all done in-situ self.run_sst(sdlfile, outfile, num_ranks=1, num_threads=1, other_args=options)