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