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