SST  7.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-2017 Sandia Corporation.
5  * This software is distributed under the BSD License.
6  * Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
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 
21 namespace SST {
22 namespace Core {
23 namespace Serialization {
24 
25 namespace pvt {
26 
27 // Functions to implement the hash for cls_id at compile time. The
28 // hash function being implemented is:
29 
30 inline uint32_t type_hash(const char* key)
31 {
32  int len = ::strlen(key);
33  uint32_t hash = 0;
34  for(int i = 0; i < len; ++i)
35  {
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  virtual const char*
113  cls_name() const = 0;
114 
115  virtual void
116  serialize_order(serializer& ser) = 0;
117 
118  virtual uint32_t
119  cls_id() const = 0;
120  virtual std::string serialization_name() const = 0;
121 
122  virtual ~serializable() { }
123 
124 protected:
125  typedef enum { ConstructorFlag } cxn_flag_t;
126  static void serializable_abort(uint32_t line, const char* file, const char* func, const char* obj);
127 };
128 
129 template <class T>
131 {
132 };
133 
134 #define ImplementVirtualSerializable(obj) \
135  protected: \
136  obj(cxn_flag_t flag){}
137 
138 
139 #define NotSerializable(obj) \
140  public: \
141  static void \
142  throw_exc(){ \
143  serializable_abort(CALL_INFO_LONG, #obj); \
144  } \
145  virtual void \
146  serialize_order(SST::Core::Serialization::serializer& UNUSED(sst)) override { \
147  throw_exc(); \
148  } \
149  virtual uint32_t \
150  cls_id() const override { \
151  throw_exc(); \
152  return -1; \
153  } \
154  static obj* \
155  construct_deserialize_stub() { \
156  throw_exc(); \
157  return 0; \
158  } \
159  virtual std::string \
160  serialization_name() const override { \
161  throw_exc(); \
162  return ""; \
163  } \
164  virtual const char* \
165  cls_name() const override { \
166  throw_exc(); \
167  return ""; \
168  }
169 
170 #define ImplementSerializableDefaultConstructor(obj) \
171  public: \
172  virtual const char* \
173  cls_name() const override { \
174  return #obj; \
175  } \
176  virtual uint32_t \
177  cls_id() const override { \
178  return SST::Core::Serialization::serializable_builder_impl<obj>::static_cls_id(); \
179  } \
180  static obj* \
181  construct_deserialize_stub() { \
182  return new obj; \
183  } \
184  virtual std::string \
185  serialization_name() const override { \
186  return #obj; \
187  } \
188 private:\
189  friend class SST::Core::Serialization::serializable_builder_impl<obj>; \
190  static bool \
191  you_forgot_to_add_ImplementSerializable_to_this_class() { \
192  return false; \
193  }
194 
195 #define ImplementSerializable(obj) \
196  public: \
197  ImplementSerializableDefaultConstructor(obj)
198 
199 
201 {
202  public:
203  virtual serializable*
204  build() const = 0;
205 
206  virtual ~serializable_builder(){}
207 
208  virtual const char*
209  name() const = 0;
210 
211  virtual uint32_t
212  cls_id() const = 0;
213 
214  virtual bool
215  sanity(serializable* ser) = 0;
216 };
217 
218 template<class T>
220 {
221  protected:
222  static const char* name_;
223  static const uint32_t cls_id_;
224 
225  public:
226  serializable*
227  build() const override {
228  return T::construct_deserialize_stub();
229  }
230 
231  const char*
232  name() const override {
233  return name_;
234  }
235 
236  uint32_t
237  cls_id() const override {
238  return cls_id_;
239  }
240 
241  static uint32_t
242  static_cls_id() {
243  return cls_id_;
244  }
245 
246  static const char*
247  static_name() {
248  return name_;
249  }
250 
251  bool
252  sanity(serializable* ser) override {
253  return (typeid(T) == typeid(*ser));
254  }
255 };
256 
258 {
259 protected:
260  typedef std::unordered_map<long, serializable_builder*> builder_map;
261  static builder_map* builders_;
262 
263  public:
264  static serializable*
265  get_serializable(uint32_t cls_id);
266 
267  /**
268  @return The cls id for the given builder
269  */
270  static uint32_t
271  // add_builder(serializable_builder* builder, uint32_t cls_id);
272  add_builder(serializable_builder* builder, const char* name);
273 
274  static bool
275  sanity(serializable* ser, uint32_t cls_id) {
276  return (*builders_)[cls_id]->sanity(ser);
277  }
278 
279  static void
280  delete_statics();
281 
282 };
283 
284 template<class T> const char* serializable_builder_impl<T>::name_ = typeid(T).name();
285 template<class T> const uint32_t serializable_builder_impl<T>::cls_id_
287  typeid(T).name());
288 
289 // Hold off on trivailly_serializable for now, as it's not really safe
290 // in the case of inheritance
291 //
292 // class trivially_serializable {
293 // };
294 
295 } // namespace Serialization
296 } // namespace Core
297 } // namespace SST
298 
299 #define SerializableName(obj) #obj
300 
301 #define DeclareSerializable(obj)
302 
303 
304 #include <sst/core/serialization/serialize_serializable.h>
305 
306 #endif
307 
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:17
Definition: serializable.h:109
static uint32_t add_builder(serializable_builder *builder, const char *name)
Definition: serializable.cc:35
Definition: serializable.h:130