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