SST  13.1.0
Structural Simulation Toolkit
sharedObject.h
1 // Copyright 2009-2023 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-2023, 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  */
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  /**
202  Destructor for SharedObjectData
203  */
204  virtual ~SharedObjectData() {}
205 };
206 
208 {
209 
210  std::map<std::string, SharedObjectData*> shared_data;
211 
212  // Mutex for locking across threads
213  static std::mutex mtx;
214  static std::mutex update_mtx;
215 
216  bool locked;
217 
218 public:
219  SharedObjectDataManager() : locked(false) {}
220 
222  {
223  for ( auto x : shared_data ) {
224  delete x.second;
225  }
226  }
227 
228  template <typename T>
229  T* getSharedObjectData(const std::string name)
230  {
231  // Need to lock since we may be initializing the
232  // SharedData object.
233  std::lock_guard<std::mutex> lock(mtx);
234  if ( locked ) {
235  Private::getSimulationOutput().fatal(
236  CALL_INFO, 1, "Attempting to initialize SharedObject %s after the init() phase\n", name.c_str());
237  }
238  auto obj = shared_data.find(name);
239  if ( obj == shared_data.end() ) {
240  // Does not yet exist, create it
241  auto ret = new T(name);
242  shared_data[name] = ret;
243  return ret;
244  }
245 
246  // If it exists, make sure the types match
247  auto obj_cast = dynamic_cast<T*>(obj->second);
248 
249  if ( obj_cast == nullptr ) {
250  Private::getSimulationOutput().fatal(
251  CALL_INFO, 1, "ERROR: Shared object %s requested with two different types\n", name.c_str());
252  }
253 
254  return obj_cast;
255  }
256 
257  void updateState(bool finalize);
258 };
259 
261 {
262 
263 public:
264  /**
265  Enum of verify types.
266  */
267  enum verify_type { VERIFY_UNINITIALIZED, FE_VERIFY, INIT_VERIFY, NO_VERIFY };
268 
269  SharedObject() {}
270  virtual ~SharedObject() {}
271 
272 protected:
273  friend class SST::Simulation_impl;
274  static SharedObjectDataManager manager;
275 
276  void incPublishCount(SharedObjectData* data) { data->incPublishCount(); }
277 
278  int incShareCount(SharedObjectData* data) { return data->incShareCount(); }
279 };
280 
281 } // namespace Shared
282 } // namespace SST
283 
284 #endif // SST_CORE_SHARED_SHAREDOBJECT_H
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
This is the base class for holding data on changes made to the shared data on each rank.
Definition: sharedObject.h:45
virtual void applyChanges(SharedObjectDataManager *UNUSED(manager))=0
Apply the changes to the name shared data.
const std::string & getName()
Get the name of the shared data the changeset should be applied to.
Definition: sharedObject.h:72
virtual void clear()=0
Clears the data.
Definition: sharedObject.h:208
Base class for holding SharedObject data.
Definition: sharedObject.h:88
virtual int getPublishCount()
Get the number of instances that have called publish() on their instance of the shared object.
Definition: sharedObject.h:124
virtual void incPublishCount()
Increment the count of instances that have called publish.
Definition: sharedObject.h:162
virtual void resetChangeSet()=0
Resets the changeset for this data on this rank.
bool isFullyPublished()
Checks to see if all instances of this SharedObject have called publish().
Definition: sharedObject.h:109
virtual int incShareCount()
Increment the count of sharers.
Definition: sharedObject.h:151
virtual SharedObjectChangeSet * getChangeSet()=0
Gets the changeset for this data on this rank.
virtual ~SharedObjectData()
Destructor for SharedObjectData.
Definition: sharedObject.h:204
virtual int getShareCount()
Get the number of sharers for this data.
Definition: sharedObject.h:116
SharedObjectData(const std::string &name)
Constructor for SharedObjectData.
Definition: sharedObject.h:193
void lock()
Called by the core when writing to shared regions is no longer allowed.
Definition: sharedObject.h:186
const std::string & getName()
Get the name of the SharedObject for this data.
Definition: sharedObject.h:99
Definition: sharedObject.h:261
verify_type
Enum of verify types.
Definition: sharedObject.h:267
Main control class for a SST Simulation.
Definition: simulation_impl.h:74