SST  14.0.0
StructuralSimulationToolkit
serializable.h
1 // Copyright 2009-2024 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-2024, 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_H
13 #define SST_CORE_SERIALIZATION_SERIALIZABLE_H
14 
15 #include "sst/core/serialization/serializer.h"
16 #include "sst/core/warnmacros.h"
17 
18 #include <limits>
19 #include <stdint.h>
20 #include <typeinfo>
21 #include <unordered_map>
22 
23 namespace SST {
24 namespace Core {
25 namespace Serialization {
26 
27 namespace pvt {
28 
29 // Functions to implement the hash for cls_id at compile time. The
30 // hash function being implemented is:
31 
32 inline uint32_t
33 type_hash(const char* key)
34 {
35  int len = ::strlen(key);
36  uint32_t hash = 0;
37  for ( int i = 0; i < len; ++i ) {
38  hash += key[i];
39  hash += (hash << 10);
40  hash ^= (hash >> 6);
41  }
42  hash += (hash << 3);
43  hash ^= (hash >> 11);
44  hash += (hash << 15);
45 
46  return hash;
47 }
48 
49 // Using constexpr is very limited, so the implementation is a bit
50 // convoluted. May be able to streamline later.
51 
52 // computes hash ^= (hash >> 6)
53 constexpr uint32_t
54 B(const uint32_t b)
55 {
56  return b ^ (b >> 6);
57 }
58 
59 // computes hash += (hash << 10)
60 constexpr uint32_t
61 A(const uint32_t a)
62 {
63  return B((a << 10) + a);
64 }
65 
66 // recursive piece that computes the for loop
67 template <size_t idx>
68 constexpr uint32_t
69 ct_hash_rec(const char* str)
70 {
71  return A(str[idx] + ct_hash_rec<idx - 1>(str));
72 }
73 
74 // End of the recursion (i.e. when you've walked back off the front of
75 // the string
76 template <>
77 constexpr uint32_t
78 ct_hash_rec<size_t(-1)>(const char* UNUSED(str))
79 {
80  return 0;
81 }
82 
83 // computes hash += (hash << 15)
84 constexpr uint32_t
85 E(const uint32_t e)
86 {
87  return (e << 15) + e;
88 }
89 
90 // computes hash ^= (hash >> 11)
91 constexpr uint32_t
92 D(const uint32_t d)
93 {
94  return E((d >> 11) ^ d);
95 }
96 
97 // computes hash += (hash << 3)
98 constexpr uint32_t
99 C(const uint32_t c)
100 {
101  return D((c << 3) + c);
102 }
103 
104 // Main function that computes the final manipulations after calling
105 // the recursive function to compute the for loop.
106 template <size_t idx>
107 constexpr uint32_t
108 ct_hash(const char* str)
109 {
110  return C(ct_hash_rec<idx>(str));
111 }
112 
113 // Macro that should be used to call the compile time hash function
114 #define COMPILE_TIME_HASH(x) (::SST::Core::Serialization::pvt::ct_hash<sizeof(x) - 2>(x))
115 
116 } // namespace pvt
117 
119 {
120 public:
121  static constexpr uint32_t NullClsId = std::numeric_limits<uint32_t>::max();
122 
123  virtual const char* cls_name() const = 0;
124 
125  virtual void serialize_order(serializer& ser) = 0;
126 
127  virtual uint32_t cls_id() const = 0;
128  virtual std::string serialization_name() const = 0;
129 
130  virtual ~serializable() {}
131 
132 protected:
133  typedef enum { ConstructorFlag } cxn_flag_t;
134  static void serializable_abort(uint32_t line, const char* file, const char* func, const char* obj);
135 };
136 
137 template <class T>
139 {};
140 
141 #define ImplementVirtualSerializable(obj) \
142 public: \
143  virtual const char* cls_name() const override { return #obj; }
144 
145 #define NotSerializable(obj) \
146 public: \
147  static void throw_exc() { ::SST::Core::Serialization::serializable::serializable_abort(CALL_INFO_LONG, #obj); } \
148  virtual void serialize_order(SST::Core::Serialization::serializer& UNUSED(sst)) override { throw_exc(); } \
149  virtual uint32_t cls_id() const override \
150  { \
151  throw_exc(); \
152  return ::SST::Core::Serialization::serializable::NullClsId; \
153  } \
154  static obj* construct_deserialize_stub() \
155  { \
156  throw_exc(); \
157  return 0; \
158  } \
159  virtual std::string serialization_name() const override \
160  { \
161  throw_exc(); \
162  return ""; \
163  } \
164  virtual const char* cls_name() const override { return #obj; }
165 
166 // virtual const char* cls_name() const override { return obj_str; }
167 #define ImplementSerializableDefaultConstructor(obj, obj_str) \
168 public: \
169  virtual const char* cls_name() const override \
170  { \
171  return SST::Core::Serialization::serializable_builder_impl<obj>::static_name(); \
172  } \
173  virtual uint32_t cls_id() const override \
174  { \
175  return SST::Core::Serialization::serializable_builder_impl<obj>::static_cls_id(); \
176  } \
177  static obj* construct_deserialize_stub() { return new obj; } \
178  virtual std::string serialization_name() const override { return obj_str; } \
179  \
180 private: \
181  friend class SST::Core::Serialization::serializable_builder_impl<obj>; \
182  static bool you_forgot_to_add_ImplementSerializable_to_this_class() { return false; }
183 
184 #define SER_FORWARD_AS_ONE(...) __VA_ARGS__
185 
186 #define ImplementSerializable(...) \
187 public: \
188  ImplementSerializableDefaultConstructor(SER_FORWARD_AS_ONE(__VA_ARGS__), #__VA_ARGS__)
189 
191 {
192 public:
193  virtual serializable* build() const = 0;
194 
195  virtual ~serializable_builder() {}
196 
197  virtual const char* name() const = 0;
198 
199  virtual uint32_t cls_id() const = 0;
200 
201  virtual bool sanity(serializable* ser) = 0;
202 };
203 
204 template <class T>
206 {
207 protected:
208  static const char* name_;
209  static const uint32_t cls_id_;
210 
211 public:
212  serializable* build() const override { return T::construct_deserialize_stub(); }
213 
214  const char* name() const override { return name_; }
215 
216  uint32_t cls_id() const override { return cls_id_; }
217 
218  static uint32_t static_cls_id() { return cls_id_; }
219 
220  static const char* static_name() { return name_; }
221 
222  bool sanity(serializable* ser) override { return (typeid(T) == typeid(*ser)); }
223 };
224 
226 {
227 protected:
228  typedef std::unordered_map<long, serializable_builder*> builder_map;
229  static builder_map* builders_;
230 
231 public:
232  static serializable* get_serializable(uint32_t cls_id);
233 
234  /**
235  @return The cls id for the given builder
236  */
237  static uint32_t
238  // add_builder(serializable_builder* builder, uint32_t cls_id);
239  add_builder(serializable_builder* builder, const char* name);
240 
241  static bool sanity(serializable* ser, uint32_t cls_id) { return (*builders_)[cls_id]->sanity(ser); }
242 
243  static void delete_statics();
244 };
245 
246 template <class T>
247 const char* serializable_builder_impl<T>::name_ = typeid(T).name();
248 template <class T>
251 
252 // Hold off on trivially_serializable for now, as it's not really safe
253 // in the case of inheritance
254 //
255 // class trivially_serializable {
256 // };
257 
258 } // namespace Serialization
259 } // namespace Core
260 } // namespace SST
261 
262 #define SerializableName(obj) #obj
263 
264 #define DeclareSerializable(obj)
265 
266 // Serialization macros for checkpoint/debug serialization
267 #define SST_SER(obj) ser& obj;
268 #define SST_SER_AS_PTR(obj) ser | obj;
269 
270 #include "sst/core/serialization/serialize_serializable.h"
271 
272 #endif
This class is basically a wrapper for objects to declare the order in which their members should be s...
Definition: serializer.h:35
Definition: action.cc:18
Definition: serializable.h:118
static uint32_t add_builder(serializable_builder *builder, const char *name)
Definition: serializable.cc:39
Definition: serializable.h:138