SST  10.1.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-2020 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){}
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 ImplementSerializable(obj) \
198  public: \
199  ImplementSerializableDefaultConstructor(obj)
200 
201 
203 {
204 public:
205  virtual serializable*
206  build() const = 0;
207 
208  virtual ~serializable_builder(){}
209 
210  virtual const char*
211  name() const = 0;
212 
213  virtual uint32_t
214  cls_id() const = 0;
215 
216  virtual bool
217  sanity(serializable* ser) = 0;
218 };
219 
220 template<class T>
222 {
223 protected:
224  static const char* name_;
225  static const uint32_t cls_id_;
226 
227 public:
228  serializable*
229  build() const override {
230  return T::construct_deserialize_stub();
231  }
232 
233  const char*
234  name() const override {
235  return name_;
236  }
237 
238  uint32_t
239  cls_id() const override {
240  return cls_id_;
241  }
242 
243  static uint32_t
244  static_cls_id() {
245  return cls_id_;
246  }
247 
248  static const char*
249  static_name() {
250  return name_;
251  }
252 
253  bool
254  sanity(serializable* ser) override {
255  return (typeid(T) == typeid(*ser));
256  }
257 };
258 
260 {
261 protected:
262  typedef std::unordered_map<long, serializable_builder*> builder_map;
263  static builder_map* builders_;
264 
265 public:
266  static serializable*
267  get_serializable(uint32_t cls_id);
268 
269  /**
270  @return The cls id for the given builder
271  */
272  static uint32_t
273  // add_builder(serializable_builder* builder, uint32_t cls_id);
274  add_builder(serializable_builder* builder, const char* name);
275 
276  static bool
277  sanity(serializable* ser, uint32_t cls_id) {
278  return (*builders_)[cls_id]->sanity(ser);
279  }
280 
281  static void
282  delete_statics();
283 
284 };
285 
286 template<class T> const char* serializable_builder_impl<T>::name_ = typeid(T).name();
287 template<class T> const uint32_t serializable_builder_impl<T>::cls_id_
289  typeid(T).name());
290 
291 // Hold off on trivially_serializable for now, as it's not really safe
292 // in the case of inheritance
293 //
294 // class trivially_serializable {
295 // };
296 
297 } // namespace Serialization
298 } // namespace Core
299 } // namespace SST
300 
301 #define SerializableName(obj) #obj
302 
303 #define DeclareSerializable(obj)
304 
305 
306 #include "sst/core/serialization/serialize_serializable.h"
307 
308 #endif
309 
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