SST 12.1.0
Structural Simulation Toolkit
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
23namespace SST {
24namespace Core {
25namespace Serialization {
26
27namespace pvt {
28
29// Functions to implement the hash for cls_id at compile time. The
30// hash function being implemented is:
31
32inline uint32_t
33type_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)
53constexpr uint32_t
54B(const uint32_t b)
55{
56 return b ^ (b >> 6);
57}
58
59// computes hash += (hash << 10)
60constexpr uint32_t
61A(const uint32_t a)
62{
63 return B((a << 10) + a);
64}
65
66// recursive piece that computes the for loop
67template <size_t idx>
68constexpr uint32_t
69ct_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
76template <>
77constexpr uint32_t
78ct_hash_rec<size_t(-1)>(const char* UNUSED(str))
79{
80 return 0;
81}
82
83// computes hash += (hash << 15)
84constexpr uint32_t
85E(const uint32_t e)
86{
87 return (e << 15) + e;
88}
89
90// computes hash ^= (hash >> 11)
91constexpr uint32_t
92D(const uint32_t d)
93{
94 return E((d >> 11) ^ d);
95}
96
97// computes hash += (hash << 3)
98constexpr uint32_t
99C(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.
106template <size_t idx>
107constexpr uint32_t
108ct_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{
120public:
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
132protected:
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
137template <class T>
139{};
140
141#define ImplementVirtualSerializable(obj) \
142public: \
143 virtual const char* cls_name() const override { return #obj; }
144
145#define NotSerializable(obj) \
146public: \
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) \
167public: \
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 \
176private: \
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(...) \
183public: \
184 ImplementSerializableDefaultConstructor(SER_FORWARD_AS_ONE(__VA_ARGS__), #__VA_ARGS__)
185
187{
188public:
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
200template <class T>
202{
203protected:
204 static const char* name_;
205 static const uint32_t cls_id_;
206
207public:
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{
223protected:
224 typedef std::unordered_map<long, serializable_builder*> builder_map;
225 static builder_map* builders_;
226
227public:
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
242template <class T>
243const char* serializable_builder_impl<T>::name_ = typeid(T).name();
244template <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
static uint32_t add_builder(serializable_builder *builder, const char *name)
Definition: serializable.cc:39
Definition: serializable.h:139
Definition: serializable.h:119
This class is basically a wrapper for objects to declare the order in which their members should be s...
Definition: serializer.h:35