SST  14.1.0
StructuralSimulationToolkit
sharedObject.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_SHARED_SHAREDOBJECT_H
13 #define SST_CORE_SHARED_SHAREDOBJECT_H
14 
15 #include "sst/core/output.h"
16 #include "sst/core/rankInfo.h"
17 #include "sst/core/serialization/serializable.h"
18 #include "sst/core/sst_types.h"
19 
20 #include <mutex>
21 #include <string>
22 
23 namespace SST {
24 
25 class Simulation_impl;
26 
27 namespace Shared {
28 
29 namespace Private {
30 Output& getSimulationOutput();
31 RankInfo getNumRanks();
32 } // namespace Private
33 
34 // NOTE: The classes in this header file are not part of the public
35 // API and can change at any time
36 
37 class SharedObjectDataManager;
38 
39 /**
40  This is the base class for holding data on changes made to the
41  shared data on each rank. This data will be serialized and shared
42  with all ranks in the simulation.
43  */
45 {
46 
47 public:
49  SharedObjectChangeSet(const std::string& name) : name(name) {}
50 
51  /**
52  Apply the changes to the name shared data.
53 
54  @param manager The SharedObjectDataManager for the rank. This
55  is used to get the named shared data.
56  */
57  virtual void applyChanges(SharedObjectDataManager* UNUSED(manager)) = 0;
58 
59  /**
60  Clears the data. Used after transfering data to other ranks to
61  prepare for the next round of init. Child classes should call
62  this version of clear() in there implementations.
63  */
64  virtual void clear() = 0;
65 
66  /**
67  Get the name of the shared data the changeset should be applied
68  to
69 
70  @return name of shared data to apply changes to
71  */
72  const std::string& getName() { return name; }
73 
74 protected:
75  void serialize_order(SST::Core::Serialization::serializer& ser) override { ser& name; }
76 
77  ImplementVirtualSerializable(SharedObjectChangeSet);
78 
79 private:
80  std::string name;
81 };
82 
83 /**
84  Base class for holding SharedObject data. The base class is needed
85  so that we can have an API to manage unknown types of objects.
86 */
88 {
89 
90  friend class SharedObjectDataManager;
91  friend class SharedObject;
92 
93 public:
94  /**
95  Get the name of the SharedObject for this data
96 
97  @return name of data
98  */
99  const std::string& getName() { return name; }
100 
101  /**
102  Checks to see if all instances of this SharedObject have called
103  publish(). This is forced to true before the setup() phase of
104  simulation, as no more writes are allowed.
105 
106  @return true if all instances have called publish(), false
107  otherwise.
108  */
109  bool isFullyPublished() { return fully_published; }
110 
111  /**
112  Get the number of sharers for this data
113 
114  @return number of sharers
115  */
116  virtual int getShareCount() { return share_count; }
117 
118  /**
119  Get the number of instances that have called publish() on their
120  instance of the shared object
121 
122  @return number of instances that have called publish()
123  */
124  virtual int getPublishCount() { return publish_count; }
125 
126 protected:
127  std::string name;
128  int share_count;
129  int publish_count;
130  bool fully_published;
131  bool locked;
132 
133  // Mutex for locking across threads
134  mutable std::mutex mtx;
135 
136  // Check to see if object data is locked. If so, fatal
137  inline void check_lock_for_write(const std::string& obj)
138  {
139  if ( locked ) {
140  Private::getSimulationOutput().fatal(
141  CALL_INFO_LONG, 1, "ERROR: attempt to write to %s %s after init phase\n", obj.c_str(), name.c_str());
142  }
143  }
144 
145  /* Manage counts */
146 
147  /**
148  Increment the count of sharers. This should only be called
149  once per instance.
150  */
151  virtual int incShareCount()
152  {
153  std::lock_guard<std::mutex> lock(mtx);
154  int ret = share_count;
155  share_count++;
156  return ret;
157  }
158  /**
159  Increment the count of instances that have called publish.
160  This should only be called once per instance.
161  */
162  virtual void incPublishCount()
163  {
164  std::lock_guard<std::mutex> lock(mtx);
165  publish_count++;
166  }
167 
168  /* For merging across ranks */
169 
170  /**
171  Gets the changeset for this data on this rank. This is called
172  by the core when exchanging and merging data
173  */
174  virtual SharedObjectChangeSet* getChangeSet() = 0;
175 
176  /**
177  Resets the changeset for this data on this rank. This is called
178  by the core when exchanging and merging data
179  */
180  virtual void resetChangeSet() = 0;
181 
182  /**
183  Called by the core when writing to shared regions is no longer
184  allowed
185  */
186  void lock() { locked = true; }
187 
188  /**
189  Constructor for SharedObjectData
190 
191  @param name name of the SharedObject
192  */
193  SharedObjectData(const std::string& name) :
194  name(name),
195  share_count(0),
196  publish_count(0),
197  fully_published(false),
198  locked(false)
199  {}
200 
201  SharedObjectData() {}
202 
203  /**
204  Destructor for SharedObjectData
205  */
206  virtual ~SharedObjectData() {}
207 
208  void serialize_order(SST::Core::Serialization::serializer& ser) override { ser& name; }
209 
210  ImplementVirtualSerializable(SharedObjectData);
211 };
212 
214 {
215 
216  std::map<std::string, SharedObjectData*> shared_data;
217 
218  // Mutex for locking across threads
219  static std::mutex mtx;
220  static std::mutex update_mtx;
221 
222  bool locked;
223 
224 public:
225  SharedObjectDataManager() : locked(false) {}
226 
228  {
229  for ( auto x : shared_data ) {
230  delete x.second;
231  }
232  }
233 
234  template <typename T>
235  T* getSharedObjectData(const std::string name)
236  {
237  // Need to lock since we may be initializing the
238  // SharedData object.
239  std::lock_guard<std::mutex> lock(mtx);
240  if ( locked ) {
241  Private::getSimulationOutput().fatal(
242  CALL_INFO, 1, "Attempting to initialize SharedObject %s after the init() phase\n", name.c_str());
243  }
244  auto obj = shared_data.find(name);
245  if ( obj == shared_data.end() ) {
246  // Does not yet exist, create it
247  auto ret = new T(name);
248  shared_data[name] = ret;
249  return ret;
250  }
251 
252  // If it exists, make sure the types match
253  auto obj_cast = dynamic_cast<T*>(obj->second);
254 
255  if ( obj_cast == nullptr ) {
256  Private::getSimulationOutput().fatal(
257  CALL_INFO, 1, "ERROR: Shared object %s requested with two different types\n", name.c_str());
258  }
259 
260  return obj_cast;
261  }
262 
263  void updateState(bool finalize);
264 
265  void serialize_order(SST::Core::Serialization::serializer& ser) override { ser& shared_data; }
266  ImplementSerializable(SST::Shared::SharedObjectDataManager)
267 };
268 
270 {
271 
272 public:
273  /**
274  Enum of verify types.
275  */
276  enum verify_type { VERIFY_UNINITIALIZED, FE_VERIFY, INIT_VERIFY, NO_VERIFY };
277 
278  SharedObject() {}
279  virtual ~SharedObject() {}
280 
281  virtual void serialize_order(SST::Core::Serialization::serializer& UNUSED(ser)) override {}
282  ImplementSerializable(SST::Shared::SharedObject)
283 
284 protected:
285  friend class SST::Simulation_impl;
286  static SharedObjectDataManager manager;
287 
288  void incPublishCount(SharedObjectData* data) { data->incPublishCount(); }
289 
290  int incShareCount(SharedObjectData* data) { return data->incShareCount(); }
291 };
292 
293 } // namespace Shared
294 } // namespace SST
295 
296 #endif // SST_CORE_SHARED_SHAREDOBJECT_H
This class is basically a wrapper for objects to declare the order in which their members should be s...
Definition: serializer.h:43
Definition: sharedObject.h:269
virtual SharedObjectChangeSet * getChangeSet()=0
Gets the changeset for this data on this rank.
virtual int getShareCount()
Get the number of sharers for this data.
Definition: sharedObject.h:116
void lock()
Called by the core when writing to shared regions is no longer allowed.
Definition: sharedObject.h:186
bool isFullyPublished()
Checks to see if all instances of this SharedObject have called publish().
Definition: sharedObject.h:109
const std::string & getName()
Get the name of the shared data the changeset should be applied to.
Definition: sharedObject.h:72
Definition: action.cc:18
SharedObjectData(const std::string &name)
Constructor for SharedObjectData.
Definition: sharedObject.h:193
verify_type
Enum of verify types.
Definition: sharedObject.h:276
Definition: serializable.h:24
virtual void incPublishCount()
Increment the count of instances that have called publish.
Definition: sharedObject.h:162
Definition: sharedObject.h:213
Main control class for a SST Simulation.
Definition: simulation_impl.h:76
virtual int getPublishCount()
Get the number of instances that have called publish() on their instance of the shared object...
Definition: sharedObject.h:124
virtual int incShareCount()
Increment the count of sharers.
Definition: sharedObject.h:151
const std::string & getName()
Get the name of the SharedObject for this data.
Definition: sharedObject.h:99
virtual void clear()=0
Clears the data.
virtual void applyChanges(SharedObjectDataManager *UNUSED(manager))=0
Apply the changes to the name shared data.
virtual void resetChangeSet()=0
Resets the changeset for this data on this rank.
This is the base class for holding data on changes made to the shared data on each rank...
Definition: sharedObject.h:44
Base class for holding SharedObject data.
Definition: sharedObject.h:87
virtual ~SharedObjectData()
Destructor for SharedObjectData.
Definition: sharedObject.h:206