SST  12.0.1
StructuralSimulationToolkit
serializable.h
1 // Copyright 2009-2022 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-2022, 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() { 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 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 #define ImplementSerializableDefaultConstructor(obj, obj_str) \
167 public: \
168  virtual const char* cls_name() const override { return obj_str; } \
169  virtual uint32_t cls_id() const override \
170  { \
171  return SST::Core::Serialization::serializable_builder_impl<obj>::static_cls_id(); \
172  } \
173  static obj* construct_deserialize_stub() { return new obj; } \
174  virtual std::string serialization_name() const override { return obj_str; } \
175  \
176 private: \
177  friend class SST::Core::Serialization::serializable_builder_impl<obj>; \
178  static bool you_forgot_to_add_ImplementSerializable_to_this_class() { return false; }
179 
180 #define SER_FORWARD_AS_ONE(...) __VA_ARGS__
181 
182 #define ImplementSerializable(...) \
183 public: \
184  ImplementSerializableDefaultConstructor(SER_FORWARD_AS_ONE(__VA_ARGS__), #__VA_ARGS__)
185 
187 {
188 public:
189  virtual serializable* build() const = 0;
190 
191  virtual ~serializable_builder() {}
192 
193  virtual const char* name() const = 0;
194 
195  virtual uint32_t cls_id() const = 0;
196 
197  virtual bool sanity(serializable* ser) = 0;
198 };
199 
200 template <class T>
202 {
203 protected:
204  static const char* name_;
205  static const uint32_t cls_id_;
206 
207 public:
208  serializable* build() const override { return T::construct_deserialize_stub(); }
209 
210  const char* name() const override { return name_; }
211 
212  uint32_t cls_id() const override { return cls_id_; }
213 
214  static uint32_t static_cls_id() { return cls_id_; }
215 
216  static const char* static_name() { return name_; }
217 
218  bool sanity(serializable* ser) override { return (typeid(T) == typeid(*ser)); }
219 };
220 
222 {
223 protected:
224  typedef std::unordered_map<long, serializable_builder*> builder_map;
225  static builder_map* builders_;
226 
227 public:
228  static serializable* get_serializable(uint32_t cls_id);
229 
230  /**
231  @return The cls id for the given builder
232  */
233  static uint32_t
234  // add_builder(serializable_builder* builder, uint32_t cls_id);
235  add_builder(serializable_builder* builder, const char* name);
236 
237  static bool sanity(serializable* ser, uint32_t cls_id) { return (*builders_)[cls_id]->sanity(ser); }
238 
239  static void delete_statics();
240 };
241 
242 template <class T>
243 const char* serializable_builder_impl<T>::name_ = typeid(T).name();
244 template <class T>
247 
248 // Hold off on trivially_serializable for now, as it's not really safe
249 // in the case of inheritance
250 //
251 // class trivially_serializable {
252 // };
253 
254 } // namespace Serialization
255 } // namespace Core
256 } // namespace SST
257 
258 #define SerializableName(obj) #obj
259 
260 #define DeclareSerializable(obj)
261 
262 #include "sst/core/serialization/serialize_serializable.h"
263 
264 #endif
This class is basically a wrapper for objects to declare the order in which their members should be s...
Definition: serializer.h:34
Definition: serializable.h:118
static uint32_t add_builder(serializable_builder *builder, const char *name)
Definition: serializable.cc:39
Definition: serializable.h:138