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