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