SST 16.0.0
Structural Simulation Toolkit
serializable_base.h
1// Copyright 2009-2026 NTESS. Under the terms
2// of Contract DE-NA0003525 with NTESS, the U.S.
3// Government retains certain rights in this software.
4//
5// Copyright (c) 2009-2026, NTESS
6// All rights reserved.
7//
8// This file is part of the SST software package. For license
9// information, see the LICENSE file in the top level directory of the
10// distribution.
11
12#ifndef SST_CORE_SERIALIZATION_SERIALIZABLE_BASE_H
13#define SST_CORE_SERIALIZATION_SERIALIZABLE_BASE_H
14
15#include "sst/core/serialization/serializer.h"
16#include "sst/core/warnmacros.h"
17
18#include <cstddef>
19#include <cstdint>
20#include <cstring>
21#include <limits>
22#include <stdint.h>
23#include <string>
24#include <typeinfo>
25#include <unordered_map>
26
27namespace SST::Core::Serialization {
28
29namespace pvt {
30
31// Functions to implement the hash for cls_id at compile time. The
32// hash function being implemented is:
33
34inline uint32_t
35type_hash(const char* key)
36{
37 int len = ::strlen(key);
38 uint32_t hash = 0;
39 for ( int i = 0; i < len; ++i ) {
40 hash += key[i];
41 hash += (hash << 10);
42 hash ^= (hash >> 6);
43 }
44 hash += (hash << 3);
45 hash ^= (hash >> 11);
46 hash += (hash << 15);
47
48 return hash;
49}
50
51// Using constexpr is very limited, so the implementation is a bit
52// convoluted. May be able to streamline later.
53
54// computes hash ^= (hash >> 6)
55constexpr uint32_t
56B(const uint32_t b)
57{
58 return b ^ (b >> 6);
59}
60
61// computes hash += (hash << 10)
62constexpr uint32_t
63A(const uint32_t a)
64{
65 return B((a << 10) + a);
66}
67
68// recursive piece that computes the for loop
69template <size_t idx>
70constexpr uint32_t
71ct_hash_rec(const char* str)
72{
73 return A(str[idx] + ct_hash_rec<idx - 1>(str));
74}
75
76// End of the recursion (i.e. when you've walked back off the front of
77// the string
78template <>
79constexpr uint32_t
80ct_hash_rec<size_t(-1)>(const char* UNUSED(str))
81{
82 return 0;
83}
84
85// computes hash += (hash << 15)
86constexpr uint32_t
87E(const uint32_t e)
88{
89 return (e << 15) + e;
90}
91
92// computes hash ^= (hash >> 11)
93constexpr uint32_t
94D(const uint32_t d)
95{
96 return E((d >> 11) ^ d);
97}
98
99// computes hash += (hash << 3)
100constexpr uint32_t
101C(const uint32_t c)
102{
103 return D((c << 3) + c);
104}
105
106// Main function that computes the final manipulations after calling
107// the recursive function to compute the for loop.
108template <size_t idx>
109constexpr uint32_t
110ct_hash(const char* str)
111{
112 return C(ct_hash_rec<idx>(str));
113}
114
115// Macro that should be used to call the compile time hash function
116#define COMPILE_TIME_HASH(x) (::SST::Core::Serialization::pvt::ct_hash<sizeof(x) - 2>(x))
117
118} // namespace pvt
119
121{
122public:
123 static constexpr uint32_t NullClsId = std::numeric_limits<uint32_t>::max();
124
125 virtual const char* cls_name() const = 0;
126
127 virtual void serialize_order(serializer& ser) = 0;
128
129 virtual uint32_t cls_id() const = 0;
130 virtual std::string serialization_name() const = 0;
131
132 virtual ~serializable_base() {}
133
134protected:
135 enum cxn_flag_t { ConstructorFlag };
136 [[noreturn]]
137 static void serializable_abort(uint32_t line, const char* file, const char* func, const char* obj);
138};
139
140
141template <class T>
143{};
144
145#define ImplementVirtualSerializable(obj) \
146 \
147public: \
148 [[noreturn]] \
149 static void throw_exc() \
150 { \
151 ::SST::Core::Serialization::serializable_base::serializable_abort(__LINE__, __FILE__, __FUNCTION__, #obj); \
152 } \
153 virtual const char* cls_name() const override \
154 { \
155 return #obj; \
156 } \
157 virtual uint32_t cls_id() const override \
158 { \
159 throw_exc(); \
160 return 0; \
161 } \
162 virtual std::string serialization_name() const override \
163 { \
164 throw_exc(); \
165 return ""; \
166 }
167
168#define NotSerializable(obj) \
169 \
170public: \
171 [[noreturn]] \
172 static void throw_exc() \
173 { \
174 ::SST::Core::Serialization::serializable_base::serializable_abort(__LINE__, __FILE__, __FUNCTION__, #obj); \
175 } \
176 virtual void serialize_order(SST::Core::Serialization::serializer& UNUSED(sst)) override \
177 { \
178 throw_exc(); \
179 } \
180 virtual uint32_t cls_id() const override \
181 { \
182 throw_exc(); \
183 return ::SST::Core::Serialization::serializable_base::NullClsId; \
184 } \
185 static obj* construct_deserialize_stub() /* NOLINT(bugprone-macro-parentheses) */ \
186 { \
187 throw_exc(); \
188 return 0; \
189 } \
190 virtual std::string serialization_name() const override \
191 { \
192 throw_exc(); \
193 return ""; \
194 } \
195 virtual const char* cls_name() const override \
196 { \
197 return #obj; \
198 }
199
200// virtual const char* cls_name() const override { return obj_str; }
201#define ImplementSerializableDefaultConstructor(obj, obj_str) \
202 \
203public: \
204 virtual const char* cls_name() const override \
205 { \
206 return SST::Core::Serialization::serializable_builder_impl<obj>::static_name(); \
207 } \
208 virtual uint32_t cls_id() const override \
209 { \
210 return SST::Core::Serialization::serializable_builder_impl<obj>::static_cls_id(); \
211 } \
212 static obj* construct_deserialize_stub() /* NOLINT(bugprone-macro-parentheses) */ \
213 { \
214 return new obj; /* NOLINT(bugprone-macro-parentheses) */ \
215 } \
216 virtual std::string serialization_name() const override \
217 { \
218 return obj_str; \
219 } \
220 \
221private: \
222 friend class SST::Core::Serialization::serializable_builder_impl<obj>; \
223 static bool you_forgot_to_add_ImplementSerializable_to_this_class() \
224 { \
225 return false; \
226 }
227
228#define SER_FORWARD_AS_ONE(...) __VA_ARGS__
229
230#define ImplementSerializable(...) \
231 \
232public: \
233 ImplementSerializableDefaultConstructor(SER_FORWARD_AS_ONE(__VA_ARGS__), #__VA_ARGS__)
234
236{
237public:
238 virtual serializable_base* build() const = 0;
239
240 virtual ~serializable_builder() {}
241
242 virtual const char* name() const = 0;
243
244 virtual uint32_t cls_id() const = 0;
245
246 virtual bool sanity(serializable_base* ser) = 0;
247};
248
249template <class T>
251{
252protected:
253 static const char* name_;
254 static const uint32_t cls_id_;
255
256public:
257 serializable_base* build() const override { return T::construct_deserialize_stub(); }
258
259 const char* name() const override { return name_; }
260
261 uint32_t cls_id() const override { return cls_id_; }
262
263 static uint32_t static_cls_id() { return cls_id_; }
264
265 static const char* static_name() { return name_; }
266
267 bool sanity(serializable_base* ser) override { return (typeid(T) == typeid(*ser)); }
268};
269
271{
272protected:
273 using builder_map = std::unordered_map<long, serializable_builder*>;
274 static builder_map* builders_;
275
276public:
277 static serializable_base* get_serializable(uint32_t cls_id);
278
279 /**
280 @return The cls id for the given builder
281 */
282 static uint32_t
283 // add_builder(serializable_builder* builder, uint32_t cls_id);
284 add_builder(serializable_builder* builder, const char* name);
285
286 static bool sanity(serializable_base* ser, uint32_t cls_id) { return (*builders_)[cls_id]->sanity(ser); }
287
288 static void delete_statics();
289};
290
291template <class T>
292const char* serializable_builder_impl<T>::name_ = typeid(T).name();
293template <class T>
294const uint32_t serializable_builder_impl<T>::cls_id_ =
296
297// Hold off on trivially_serializable for now, as it's not really safe
298// in the case of inheritance
299//
300// class trivially_serializable {
301// };
302
303} // namespace SST::Core::Serialization
304
305#define SerializableName(obj) #obj
306
307#define DeclareSerializable(obj)
308
309// #include "sst/core/serialization/serialize_serializable_base.h"
310
311#endif
Definition serializable_base.h:121
Definition serializable_base.h:251
Definition serializable_base.h:236
Definition serializable_base.h:271
static uint32_t add_builder(serializable_builder *builder, const char *name)
Definition serializable_base.cc:37
Definition serializable_base.h:143
This class is basically a wrapper for objects to declare the order in which their members should be s...
Definition serializer.h:43