SST  14.1.0
StructuralSimulationToolkit
serializer.h
1 // Copyright 2009-2024 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-2024, 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_SERIALIZER_H
13 #define SST_CORE_SERIALIZATION_SERIALIZER_H
14 
15 // These includes have guards to print warnings if they are included
16 // independent of this file. Set the #define that will disable the
17 // warnings.
18 #define SST_INCLUDING_SERIALIZER_H
19 #include "sst/core/serialization/impl/mapper.h"
20 #include "sst/core/serialization/impl/packer.h"
21 #include "sst/core/serialization/impl/sizer.h"
22 #include "sst/core/serialization/impl/unpacker.h"
23 // Reenble warnings for including the above file independent of this
24 // file.
25 #undef SST_INCLUDING_SERIALIZER_H
26 
27 #include <cstdint>
28 #include <cstring>
29 #include <list>
30 #include <map>
31 #include <set>
32 #include <typeinfo>
33 #include <vector>
34 
35 namespace SST {
36 namespace Core {
37 namespace Serialization {
38 
39 /**
40  * This class is basically a wrapper for objects to declare the order in
41  * which their members should be ser/des
42  */
44 {
45 public:
46  enum SERIALIZE_MODE { SIZER, PACK, UNPACK, MAP };
47 
48 public:
49  serializer() : mode_(SIZER) // just sizing by default
50  {}
51 
52  pvt::ser_mapper& mapper() { return mapper_; }
53 
54  pvt::ser_packer& packer() { return packer_; }
55 
56  pvt::ser_unpacker& unpacker() { return unpacker_; }
57 
58  pvt::ser_sizer& sizer() { return sizer_; }
59 
60  template <class T>
61  void size(T& t)
62  {
63  sizer_.size<T>(t);
64  }
65 
66  template <class T>
67  void pack(T& t)
68  {
69  packer_.pack<T>(t);
70  }
71 
72  template <class T>
73  void unpack(T& t)
74  {
75  unpacker_.unpack<T>(t);
76  }
77 
78  virtual ~serializer() {}
79 
80  SERIALIZE_MODE
81  mode() const { return mode_; }
82 
83  void set_mode(SERIALIZE_MODE mode) { mode_ = mode; }
84 
85  void reset()
86  {
87  sizer_.reset();
88  packer_.reset();
89  unpacker_.reset();
90  }
91 
92  template <typename T>
93  void primitive(T& t)
94  {
95  switch ( mode_ ) {
96  case SIZER:
97  sizer_.size(t);
98  break;
99  case PACK:
100  packer_.pack(t);
101  break;
102  case UNPACK:
103  unpacker_.unpack(t);
104  break;
105  case MAP:
106  break;
107  }
108  }
109 
110  template <class T, int N>
111  void array(T arr[N])
112  {
113  switch ( mode_ ) {
114  case SIZER:
115  {
116  sizer_.add(sizeof(T) * N);
117  break;
118  }
119  case PACK:
120  {
121  char* charstr = packer_.next_str(N * sizeof(T));
122  ::memcpy(charstr, arr, N * sizeof(T));
123  break;
124  }
125  case UNPACK:
126  {
127  char* charstr = unpacker_.next_str(N * sizeof(T));
128  ::memcpy(arr, charstr, N * sizeof(T));
129  break;
130  }
131  case MAP:
132  break;
133  }
134  }
135 
136  template <typename T, typename Int>
137  void binary(T*& buffer, Int& size)
138  {
139  switch ( mode_ ) {
140  case SIZER:
141  {
142  sizer_.add(sizeof(Int));
143  sizer_.add(size);
144  break;
145  }
146  case PACK:
147  {
148  if ( buffer ) {
149  packer_.pack(size);
150  packer_.pack_buffer(buffer, size * sizeof(T));
151  }
152  else {
153  Int nullsize = 0;
154  packer_.pack(nullsize);
155  }
156  break;
157  }
158  case UNPACK:
159  {
160  unpacker_.unpack(size);
161  if ( size != 0 ) { unpacker_.unpack_buffer(&buffer, size * sizeof(T)); }
162  else {
163  buffer = nullptr;
164  }
165  break;
166  }
167  case MAP:
168  break;
169  }
170  }
171 
172  // For void*, we get sizeof(void), which errors.
173  // Create a wrapper that casts to char* and uses above
174  template <typename Int>
175  void binary(void*& buffer, Int& size)
176  {
177  char* tmp = (char*)buffer;
178  binary<char>(tmp, size);
179  buffer = tmp;
180  }
181 
182  void string(std::string& str);
183 
184  void start_packing(char* buffer, size_t size)
185  {
186  packer_.init(buffer, size);
187  mode_ = PACK;
188  ser_pointer_set.clear();
189  ser_pointer_map.clear();
190  }
191 
192  void start_sizing()
193  {
194  sizer_.reset();
195  mode_ = SIZER;
196  ser_pointer_set.clear();
197  ser_pointer_map.clear();
198  }
199 
200  void start_unpacking(char* buffer, size_t size)
201  {
202  unpacker_.init(buffer, size);
203  mode_ = UNPACK;
204  ser_pointer_set.clear();
205  ser_pointer_map.clear();
206  }
207 
208  void start_mapping(ObjectMap* obj)
209  {
210  mapper_.init(obj);
211  mode_ = MAP;
212  }
213 
214  size_t size() const
215  {
216  switch ( mode_ ) {
217  case SIZER:
218  return sizer_.size();
219  case PACK:
220  return packer_.size();
221  case UNPACK:
222  return unpacker_.size();
223  case MAP:
224  break;
225  }
226  return 0;
227  }
228 
229  inline bool check_pointer_pack(uintptr_t ptr)
230  {
231  if ( ser_pointer_set.count(ptr) == 0 ) {
232  ser_pointer_set.insert(ptr);
233  return false;
234  }
235  return true;
236  }
237 
238  inline uintptr_t check_pointer_unpack(uintptr_t ptr)
239  {
240  auto it = ser_pointer_map.find(ptr);
241  if ( it != ser_pointer_map.end() ) { return it->second; }
242  // Keep a copy of the ptr in case we have a split report
243  split_key = ptr;
244  return 0;
245  }
246 
247  ObjectMap* check_pointer_map(uintptr_t ptr)
248  {
249  auto it = ser_pointer_map.find(ptr);
250  if ( it != ser_pointer_map.end() ) { return reinterpret_cast<ObjectMap*>(it->second); }
251  return nullptr;
252  }
253 
254  inline void report_new_pointer(uintptr_t real_ptr) { ser_pointer_map[split_key] = real_ptr; }
255 
256  inline void report_real_pointer(uintptr_t ptr, uintptr_t real_ptr) { ser_pointer_map[ptr] = real_ptr; }
257 
258  void enable_pointer_tracking(bool value = true) { enable_ptr_tracking_ = value; }
259 
260  inline bool is_pointer_tracking_enabled() { return enable_ptr_tracking_; }
261 
262  inline void report_object_map(ObjectMap* ptr)
263  {
264  ser_pointer_map[reinterpret_cast<uintptr_t>(ptr->getAddr())] = reinterpret_cast<uintptr_t>(ptr);
265  }
266 
267 protected:
268  // only one of these is going to be valid for this serializer
269  // not very good class design, but a little more convenient
270  pvt::ser_packer packer_;
271  pvt::ser_unpacker unpacker_;
272  pvt::ser_sizer sizer_;
273  pvt::ser_mapper mapper_;
274  SERIALIZE_MODE mode_;
275  bool enable_ptr_tracking_ = false;
276 
277  std::set<uintptr_t> ser_pointer_set;
278  // Used for unpacking and mapping
279  std::map<uintptr_t, uintptr_t> ser_pointer_map;
280  uintptr_t split_key;
281 };
282 
283 } // namespace Serialization
284 } // namespace Core
285 } // namespace SST
286 
287 #endif // SST_CORE_SERIALIZATION_SERIALIZER_H
This class is basically a wrapper for objects to declare the order in which their members should be s...
Definition: serializer.h:43
void unpack_buffer(void *buf, int size)
unpack_buffer
Definition: serializer.cc:25
Definition: action.cc:18
Class created by the serializer mapping mode used to map the variables for objects.
Definition: objectMap.h:61
virtual void * getAddr()=0
Get the address of the variable represented by the ObjectMap.
void pack_buffer(void *buf, int size)
pack_buffer
Definition: serializer.cc:39