SST  15.1.0
StructuralSimulationToolkit
sharedArray.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_SHAREDARRAY_H
13 #define SST_CORE_SHARED_SHAREDARRAY_H
14 
15 #include "sst/core/serialization/serializable.h"
16 #include "sst/core/shared/sharedObject.h"
17 #include "sst/core/sst_types.h"
18 
19 #include <cstddef>
20 #include <mutex>
21 #include <string>
22 #include <vector>
23 
24 namespace SST::Shared {
25 
26 /**
27  SharedArray class. The class is templated to allow for an array
28  of any non-pointer type. The type must be serializable.
29  */
30 template <typename T>
31 class SharedArray : public SharedObject
32 {
33  static_assert(!std::is_pointer_v<T>, "Cannot use a pointer type with SharedArray");
34 
35  // Forward declaration. Defined below
36  class Data;
37 
38 public:
39  /**
40  Default constructor for SharedArray.
41  */
43  SharedObject(),
44  published(false),
45  data(nullptr)
46  {}
47 
48  /**
49  Shared Array Destructor
50  */
52  {
53  // data does not need to be deleted since the
54  // SharedObjectManager owns the pointer
55  }
56 
57  /**
58  Initialize the SharedArray.
59 
60  @param obj_name Name of the object. This name is how the
61  object is uniquely identified across ranks.
62 
63  @param length Length of the array. The length can be 0 if no
64  data is going to be written by the calling element, otherwise,
65  it must be large enough to write the desired data. The final
66  length of the array will be the maximum of the requested
67  lengths. The length of the array can be queried using the
68  size() method.
69 
70  @param init_value value that entries should be initialized to.
71  By default, each array item will be initialized using the
72  default constructor for the class being stored.
73 
74  @param verify_mode Specifies how multiply written data should
75  be verified. FE_VERIFY uses a full/empty bit for each entry
76  and if a value has previously been written, it will make sure
77  the two values match. INIT_VERIFY will simply compare writes
78  against the current value and will error unless the values
79  aren't the same or the existing value is the init_value. When
80  NO_VERIFY is passed, no verification will occur. This is
81  mostly useful when you can guarantee that multiple elements
82  won't write the same value and you want to do in-place
83  modifications as you initialize. VERIFY_UNINITIALIZED is a
84  reserved value and should not be passed.
85 
86  @return returns the number of instances that have intialized
87  themselve before this instance on this MPI rank.
88  */
89  int initialize(const std::string& obj_name, size_t length = 0, T init_value = T(), verify_type v_type = INIT_VERIFY)
90  {
91  if ( data ) {
92  Private::getSimulationOutput().fatal(
93  CALL_INFO, 1, "ERROR: called initialize() of SharedArray %s more than once\n", obj_name.c_str());
94  }
95 
96  if ( v_type == VERIFY_UNINITIALIZED ) {
97  Private::getSimulationOutput().fatal(CALL_INFO, 1,
98  "ERROR: VERIFY_UNINITIALIZED passed into instance of SharedArray %s. "
99  "This is a reserved value and cannot be passed in here. \n",
100  obj_name.c_str());
101  }
102 
103  data = manager.getSharedObjectData<Data>(obj_name);
104  int ret = incShareCount(data);
105  if ( length != 0 ) data->setSize(length, init_value, v_type);
106  return ret;
107  }
108 
109  /*** Typedefs and functions to mimic parts of the vector API ***/
110 
111  using const_iterator = typename std::vector<T>::const_iterator;
112  using const_reverse_iterator = typename std::vector<T>::const_reverse_iterator;
113 
114  /**
115  Get the length of the array.
116 
117  @return length of the array
118  */
119  inline size_t size() const { return data->getSize(); }
120 
121  /**
122  Tests if array is empty.
123 
124  @return true if array is empty (size = 0), false otherwise
125  */
126  inline bool empty() const { return data->array.empty(); }
127 
128  /**
129  Get const_iterator to beginning of underlying map
130  */
131  const_iterator begin() const { return data->array.cbegin(); }
132 
133  /**
134  Get const_iterator to end of underlying map
135  */
136  const_iterator end() const { return data->array.cend(); }
137 
138  /**
139  Get const_reverse_iterator to beginning of underlying map
140  */
141  const_reverse_iterator rbegin() const { return data->array.crbegin(); }
142 
143  /**
144  Get const_reverse_iterator to end of underlying map
145  */
146  const_reverse_iterator rend() const { return data->array.crend(); }
147 
148  /**
149  Indicate that the calling element has written all the data it
150  plans to write. Writing to the array through this instance
151  after publish() is called will create an error.
152  */
153  void publish()
154  {
155  if ( published ) return;
156  published = true;
157  incPublishCount(data);
158  }
159 
160  /**
161  Check whether all instances of this SharedArray have called
162  publish(). NOTE: Is is possible that this could return true
163  one round, but false the next if a new instance of the
164  SharedArray was initialized but not published after the last
165  call.
166  */
167  bool isFullyPublished() { return data->isFullyPublished(); }
168 
169  /**
170  Write data to the array. This function is thread-safe, as a
171  mutex is used to ensure only one write at a time.
172 
173  @param index index of the write
174 
175  @param value value to be written
176  */
177  inline void write(int index, const T& value)
178  {
179  if ( published ) {
180  Private::getSimulationOutput().fatal(
181  CALL_INFO, 1, "ERROR: write to SharedArray %s after publish() was called\n", data->getName().c_str());
182  }
183  return data->write(index, value);
184  }
185 
186  /**
187  Read data from the array. This returns a const reference, so
188  is read only.
189 
190  NOTE: This function does not use a mutex, so it is possible to
191  get invalid results if another thread caused a resize of the
192  underlying data structure at the same time as the read.
193  However, after the init() phase of simulation is complete (in
194  setup() and beyond), this is always a safe operation. If
195  reading during init() and you can't guarantee that all elements
196  have already written all data to the SharedArray, use
197  mutex_read() to guarantee thread safety.
198 
199  @param index index to read
200 
201  @return const reference to data at index
202  */
203  inline const T& operator[](int index) const { return data->read(index); }
204 
205  /**
206  Read data from the array. This returns a const reference, so
207  is read only. This version of read is always thread safe (@see
208  operator[]).
209 
210  @param index index to read
211 
212  @return const reference to data at index
213  */
214  inline const T& mutex_read(int index) const { return data->mutex_read(index); }
215 
216  void serialize_order(SST::Core::Serialization::serializer& ser) override
217  {
218  SST::Shared::SharedObject::serialize_order(ser);
219  SST_SER(published);
220  bool initialized = (data != nullptr);
221  SST_SER(initialized);
222 
223  if ( !initialized ) return;
224 
225  switch ( ser.mode() ) {
226  case SST::Core::Serialization::serializer::SIZER:
227  case SST::Core::Serialization::serializer::PACK:
228  {
229  std::string name = data->getName();
230  SST_SER(name);
231  break;
232  }
233  case SST::Core::Serialization::serializer::UNPACK:
234  {
235  std::string name;
236  SST_SER(name);
237  data = manager.getSharedObjectData<Data>(name);
238  break;
239  }
240  case SST::Core::Serialization::serializer::MAP:
241  // Add your code here
242  break;
243  };
244  }
245  ImplementSerializable(SST::Shared::SharedArray<T>)
246 
247 private:
248  bool published;
249  Data* data = nullptr;
250 
251  class Data : public SharedObjectData
252  {
253 
254  // Forward declaration. Defined below
255  class ChangeSet;
256 
257  public:
258  std::vector<T> array;
259  std::vector<bool> written;
260  ChangeSet* change_set;
261  T init;
262  verify_type verify;
263 
264  Data() :
266  change_set(nullptr),
267  verify(VERIFY_UNINITIALIZED)
268  {}
269  explicit Data(const std::string& name) :
270  SharedObjectData(name),
271  change_set(nullptr),
272  verify(VERIFY_UNINITIALIZED)
273  {
274  if ( Private::getNumRanks().rank > 1 ) {
275  change_set = new ChangeSet(name);
276  }
277  }
278 
279  ~Data()
280  {
281  if ( change_set ) delete change_set;
282  }
283 
284  /**
285  Set the size of the array. An element can only write up to the
286  current size (reading or writing beyond the size will create
287  undefined behavior). However, an element can put in the size
288  it needs for it's writes and it will end up being the largest
289  size requested. We use a vector underneatch the covers to
290  manage the memory/copying of data.
291  */
292  void setSize(size_t size, const T& init_data, verify_type v_type)
293  {
294  // If the data is uninitialized, then there is nothing to do
295  if ( v_type == VERIFY_UNINITIALIZED ) return;
296  std::lock_guard<std::mutex> lock(mtx);
297  if ( size > array.size() ) {
298  // Need to resize the vector
299  array.resize(size, init_data);
300  if ( v_type == FE_VERIFY ) {
301  written.resize(size);
302  }
303  if ( change_set ) change_set->setSize(size, init_data, v_type);
304  }
305  // init and verify must match across all intances. We can
306  // tell that they have been when verify is not
307  // VERIFY_UNINITIALIZED.
308  if ( verify != VERIFY_UNINITIALIZED ) {
309  if ( init != init_data ) {
310  Private::getSimulationOutput().fatal(CALL_INFO, 1,
311  "ERROR: Two different init_data values passed into SharedArray %s\n", name.c_str());
312  }
313 
314  if ( verify != v_type ) {
315  Private::getSimulationOutput().fatal(
316  CALL_INFO, 1, "ERROR: Two different verify types passed into SharedArray %s\n", name.c_str());
317  }
318  }
319  init = init_data;
320  verify = v_type;
321  }
322 
323  size_t getSize()
324  {
325  std::lock_guard<std::mutex> lock(mtx);
326  return array.size();
327  }
328 
329  void update_write(int index, const T& data)
330  {
331  // Don't need to mutex because this is only ever called
332  // from one thread at a time, with barrier before and
333  // after, or from write(), which does mutex.
334  bool check = false;
335  switch ( verify ) {
336  case FE_VERIFY:
337  check = written[index];
338  break;
339  case INIT_VERIFY:
340  check = array[index] != init;
341  break;
342  default:
343  break;
344  }
345  if ( check && (array[index] != data) ) {
346  Private::getSimulationOutput().fatal(CALL_INFO, 1,
347  "ERROR: wrote two different values to index %d of SharedArray %s\n", index, name.c_str());
348  }
349  array[index] = data;
350  if ( verify == FE_VERIFY ) written[index] = true;
351  }
352 
353  void write(int index, const T& data)
354  {
355  std::lock_guard<std::mutex> lock(mtx);
356  check_lock_for_write("SharedArray");
357  update_write(index, data);
358  if ( verify == FE_VERIFY ) written[index] = true;
359  if ( change_set ) change_set->addChange(index, data);
360  }
361 
362  // Inline the read since it may be called often during run().
363  // This read is not protected from data races in the case where
364  // the array may be resized by another thread. If there is a
365  // danger of the array being resized during init, use the
366  // mutex_read function until after the init phase.
367  inline const T& read(int index) const { return array[index]; }
368 
369  // Mutexed read for use if you are resizing the array as you go
370  inline const T& mutex_read(int index) const
371  {
372  std::lock_guard<std::mutex> lock(mtx);
373  return array[index];
374  }
375 
376  // Functions inherited from SharedObjectData
377  virtual SharedObjectChangeSet* getChangeSet() override { return change_set; }
378  virtual void resetChangeSet() override { change_set->clear(); }
379 
380  void serialize_order(SST::Core::Serialization::serializer& ser) override
381  {
382  SharedObjectData::serialize_order(ser);
383  SST_SER(array);
384  }
385 
386  ImplementSerializable(SST::Shared::SharedArray<T>::Data);
387 
388  private:
389  class ChangeSet : public SharedObjectChangeSet
390  {
391 
392  std::vector<std::pair<int, T>> changes;
393  size_t size;
394  T init;
395  verify_type verify;
396 
397  void serialize_order(SST::Core::Serialization::serializer& ser) override
398  {
399  SharedObjectChangeSet::serialize_order(ser);
400  SST_SER(changes);
401  SST_SER(size);
402  SST_SER(init);
403  SST_SER(verify);
404  }
405 
406  ImplementSerializable(SST::Shared::SharedArray<T>::Data::ChangeSet);
407 
408  public:
409  // For serialization
410  ChangeSet() :
411  SharedObjectChangeSet()
412  {}
413  explicit ChangeSet(const std::string& name) :
414  SharedObjectChangeSet(name),
415  size(0),
416  verify(VERIFY_UNINITIALIZED)
417  {}
418 
419  void addChange(int index, const T& value) { changes.emplace_back(index, value); }
420 
421  void setSize(size_t length, const T& init_data, verify_type v_type)
422  {
423  size = length;
424  init = init_data;
425  verify = v_type;
426  }
427  size_t getSize() { return size; }
428 
429  void applyChanges(SharedObjectDataManager* manager) override
430  {
431  auto data = manager->getSharedObjectData<Data>(getName());
432  data->setSize(size, init, verify);
433  for ( auto x : changes ) {
434  data->update_write(x.first, x.second);
435  }
436  }
437 
438  void clear() override { changes.clear(); }
439  };
440  };
441 };
442 
443 /**
444  SharedArray class. The class is templated to allow for an array
445  of any non-pointer type. The type must be serializable.
446  */
447 template <>
448 class SharedArray<bool> : public SharedObject
449 {
450  // Forward declaration. Defined below
451  class Data;
452 
453 public:
454  /**
455  Default constructor for SharedArray.
456  */
458  SharedObject(),
459  published(false),
460  data(nullptr)
461  {}
462 
463  /**
464  Shared Array Destructor
465  */
467  {
468  // data does not need to be deleted since the
469  // SharedObjectManager owns the pointer
470  }
471 
472  /**
473  Initialize the SharedArray.
474 
475  @param obj_name Name of the object. This name is how the
476  object is uniquely identified across ranks.
477 
478  @param length Length of the array. The length can be 0 if no
479  data is going to be written by the calling element, otherwise,
480  it must be large enough to write the desired data. The final
481  length of the array will be the maximum of the requested
482  lengths. The length of the array can be queried using the
483  size() method.
484 
485  @param init_value value that entries should be initialized to.
486  By default, each array item will be initialized using the
487  default constructor for the class being stored.
488 
489  @param verify_mode Specifies how multiply written data should
490  be verified. FE_VERIFY uses a full/empty bit for each entry
491  and if a value has previously been written, it will make sure
492  the two values match. INIT_VERIFY will simply compare writes
493  against the current value and will error unless the values
494  aren't the same or the existing value is the init_value. When
495  NO_VERIFY is passed, no verification will occur. This is
496  mostly useful when you can guarantee that multiple elements
497  won't write the same value and you want to do in-place
498  modifications as you initialize. VERIFY_UNINITIALIZED is a
499  reserved value and should not be passed.
500 
501  @return returns the number of instances that have intialized
502  themselve before this instance on this MPI rank.
503  */
505  const std::string& obj_name, size_t length = 0, bool init_value = false, verify_type v_type = INIT_VERIFY)
506  {
507  if ( data ) {
508  Private::getSimulationOutput().fatal(
509  CALL_INFO, 1, "ERROR: called initialize() of SharedArray %s more than once\n", obj_name.c_str());
510  }
511 
512  if ( v_type == VERIFY_UNINITIALIZED ) {
513  Private::getSimulationOutput().fatal(CALL_INFO, 1,
514  "ERROR: VERIFY_UNINITIALIZED passed into instance of SharedArray %s. "
515  "This is a reserved value and cannot be passed in here. \n",
516  obj_name.c_str());
517  }
518  data = manager.getSharedObjectData<Data>(obj_name);
519  int ret = incShareCount(data);
520  if ( length != 0 ) {
521  data->setSize(length, init_value, v_type);
522  }
523 
524  return ret;
525  }
526 
527  /*** Typedefs and functions to mimic parts of the vector API ***/
528 
529  using const_iterator = typename std::vector<bool>::const_iterator;
530  using const_reverse_iterator = typename std::vector<bool>::const_reverse_iterator;
531 
532  /**
533  Get the length of the array.
534 
535  @return length of the array
536  */
537  inline size_t size() const { return data->getSize(); }
538 
539  /**
540  Tests if array is empty.
541 
542  @return true if array is empty (size = 0), false otherwise
543  */
544  inline bool empty() const { return data->array.empty(); }
545 
546  /**
547  Get const_iterator to beginning of underlying map
548  */
549  const_iterator begin() const { return data->array.cbegin(); }
550 
551  /**
552  Get const_iterator to end of underlying map
553  */
554  const_iterator end() const { return data->array.cend(); }
555 
556  /**
557  Get const_reverse_iterator to beginning of underlying map
558  */
559  const_reverse_iterator rbegin() const { return data->array.crbegin(); }
560 
561  /**
562  Get const_reverse_iterator to end of underlying map
563  */
564  const_reverse_iterator rend() const { return data->array.crend(); }
565 
566  /**
567  Indicate that the calling element has written all the data it
568  plans to write. Writing to the array through this instance
569  after publish() is called will create an error.
570  */
571  void publish()
572  {
573  if ( published ) return;
574  published = true;
575  incPublishCount(data);
576  }
577 
578  /**
579  Check whether all instances of this SharedArray have called
580  publish(). NOTE: Is is possible that this could return true
581  one round, but false the next if a new instance of the
582  SharedArray was initialized but not published after the last
583  call.
584  */
585  bool isFullyPublished() { return data->isFullyPublished(); }
586 
587  /**
588  Write data to the array. This function is thread-safe, as a
589  mutex is used to ensure only one write at a time.
590 
591  @param index index of the write
592 
593  @param value value to be written
594  */
595  inline void write(int index, bool value)
596  {
597  if ( published ) {
598  Private::getSimulationOutput().fatal(
599  CALL_INFO, 1, "ERROR: write to SharedArray %s after publish() was called\n", data->getName().c_str());
600  }
601  return data->write(index, value);
602  }
603 
604  /**
605  Read data from the array. This returns a const reference, so
606  is read only.
607 
608  NOTE: This function does not use a mutex, so it is possible to
609  get invalid results if another thread caused a resize of the
610  underlying data structure at the same time as the read.
611  However, after the init() phase of simulation is complete (in
612  setup() and beyond), this is always a safe operation. If
613  reading during init() and you can't guarantee that all elements
614  have already written all data to the SharedArray, use
615  mutex_read() to guarantee thread safety.
616 
617  @param index index to read
618 
619  @return const reference to data at index
620  */
621  inline bool operator[](int index) const { return data->read(index); }
622 
623  /**
624  Read data from the array. This returns a const reference, so
625  is read only. This version of read is always thread safe (@see
626  operator[]).
627 
628  @param index index to read
629 
630  @return const reference to data at index
631  */
632  inline bool mutex_read(int index) const { return data->mutex_read(index); }
633 
634  void serialize_order(SST::Core::Serialization::serializer& ser) override
635  {
636  SST::Shared::SharedObject::serialize_order(ser);
637  SST_SER(published);
638  bool initialized = (data != nullptr);
639  SST_SER(initialized);
640 
641  if ( !initialized ) return;
642 
643  switch ( ser.mode() ) {
644  case SST::Core::Serialization::serializer::SIZER:
645  case SST::Core::Serialization::serializer::PACK:
646  {
647  std::string name = data->getName();
648  SST_SER(name);
649  break;
650  }
651  case SST::Core::Serialization::serializer::UNPACK:
652  {
653  std::string name;
654  SST_SER(name);
655  data = manager.getSharedObjectData<Data>(name);
656  break;
657  }
658  case SST::Core::Serialization::serializer::MAP:
659  // Add your code here
660  break;
661  };
662  }
663  ImplementSerializable(SST::Shared::SharedArray<bool>)
664 
665 private:
666  bool published;
667  Data* data = nullptr;
668 
669  class Data : public SharedObjectData
670  {
671 
672  // Forward declaration. Defined below
673  class ChangeSet;
674 
675  public:
676  std::vector<bool> array;
677  std::vector<bool> written;
678  ChangeSet* change_set;
679  bool init;
680  verify_type verify;
681 
682  Data() :
684  change_set(nullptr),
685  verify(VERIFY_UNINITIALIZED)
686  {} // For serialization ONLY
687  explicit Data(const std::string& name) :
688  SharedObjectData(name),
689  change_set(nullptr),
690  verify(VERIFY_UNINITIALIZED)
691  {
692  if ( Private::getNumRanks().rank > 1 ) {
693  change_set = new ChangeSet(name);
694  }
695  }
696 
697  ~Data()
698  {
699  if ( change_set ) delete change_set;
700  }
701 
702  /**
703  Set the size of the array. An element can only write up to the
704  current size (reading or writing beyond the size will create
705  undefined behavior). However, an element can put in the size
706  it needs for its writes and it will end up being the largest
707  size requested. We use a vector underneatch the covers to
708  manage the memory/copying of data.
709  */
710  void setSize(size_t size, bool init_data, verify_type v_type)
711  {
712  // If the data is uninitialized, then there is nothing to do
713  if ( v_type == VERIFY_UNINITIALIZED ) return;
714  std::lock_guard<std::mutex> lock(mtx);
715  if ( size > array.size() ) {
716  // Need to resize the vector
717  array.resize(size, init_data);
718  if ( v_type == FE_VERIFY ) {
719  written.resize(size);
720  }
721  if ( change_set ) change_set->setSize(size, init_data, v_type);
722  }
723  // init and verify must match across all intances. We can
724  // tell that they have been when verify is not
725  // VERIFY_UNINITIALIZED.
726  if ( verify != VERIFY_UNINITIALIZED ) {
727  if ( init != init_data ) {
728  Private::getSimulationOutput().fatal(CALL_INFO, 1,
729  "ERROR: Two different init_data values passed into SharedArray %s\n", name.c_str());
730  }
731 
732  if ( verify != v_type ) {
733  Private::getSimulationOutput().fatal(
734  CALL_INFO, 1, "ERROR: Two different verify types passed into SharedArray %s\n", name.c_str());
735  }
736  }
737  init = init_data;
738  verify = v_type;
739  }
740 
741  size_t getSize()
742  {
743  std::lock_guard<std::mutex> lock(mtx);
744  return array.size();
745  }
746 
747  void update_write(int index, bool data)
748  {
749  // Don't need to mutex because this is only ever called
750  // from one thread at a time, with barrier before and
751  // after, or from write(), which does mutex.
752  bool check = false;
753  switch ( verify ) {
754  case FE_VERIFY:
755  check = written[index];
756  break;
757  case INIT_VERIFY:
758  check = array[index] != init;
759  break;
760  default:
761  break;
762  }
763  if ( check && (array[index] != data) ) {
764  Private::getSimulationOutput().fatal(CALL_INFO, 1,
765  "ERROR: wrote two different values to index %d of SharedArray %s\n", index, name.c_str());
766  }
767  array[index] = data;
768  if ( verify == FE_VERIFY ) written[index] = true;
769  }
770 
771  void write(int index, bool data)
772  {
773  std::lock_guard<std::mutex> lock(mtx);
774  check_lock_for_write("SharedArray");
775  update_write(index, data);
776  if ( verify == FE_VERIFY ) written[index] = true;
777  if ( change_set ) change_set->addChange(index, data);
778  }
779 
780  // Inline the read since it may be called often during run().
781  // This read is not protected from data races in the case where
782  // the array may be resized by another thread. If there is a
783  // danger of the array being resized during init, use the
784  // mutex_read function until after the init phase.
785  inline bool read(int index) const { return array[index]; }
786 
787  // Mutexed read for use if you are resizing the array as you go
788  inline bool mutex_read(int index) const
789  {
790  std::lock_guard<std::mutex> lock(mtx);
791  return array[index];
792  }
793 
794  // Functions inherited from SharedObjectData
795  virtual SharedObjectChangeSet* getChangeSet() override { return change_set; }
796  virtual void resetChangeSet() override { change_set->clear(); }
797 
798  void serialize_order(SST::Core::Serialization::serializer& ser) override
799  {
800  SharedObjectData::serialize_order(ser);
801  SST_SER(array);
802  // All other members are not needed past init()
803  }
804 
805  ImplementSerializable(SST::Shared::SharedArray<bool>::Data);
806 
807  private:
808  class ChangeSet : public SharedObjectChangeSet
809  {
810 
811  std::vector<std::pair<int, bool>> changes;
812  size_t size;
813  bool init;
814  verify_type verify;
815 
816  void serialize_order(SST::Core::Serialization::serializer& ser) override
817  {
818  SharedObjectChangeSet::serialize_order(ser);
819  SST_SER(changes);
820  SST_SER(size);
821  SST_SER(init);
822  SST_SER(verify);
823  }
824 
826 
827  public:
828  // For serialization
829  ChangeSet() :
830  SharedObjectChangeSet()
831  {}
832  explicit ChangeSet(const std::string& name) :
833  SharedObjectChangeSet(name),
834  size(0),
835  verify(VERIFY_UNINITIALIZED)
836  {}
837 
838  void addChange(int index, bool value) { changes.emplace_back(index, value); }
839 
840  void setSize(size_t length, bool init_data, verify_type v_type)
841  {
842  size = length;
843  init = init_data;
844  verify = v_type;
845  }
846  size_t getSize() { return size; }
847 
848  void applyChanges(SharedObjectDataManager* manager) override
849  {
850  auto data = manager->getSharedObjectData<Data>(getName());
851  data->setSize(size, init, verify);
852  for ( auto x : changes ) {
853  data->update_write(x.first, x.second);
854  }
855  }
856 
857  void clear() override { changes.clear(); }
858  };
859  };
860 };
861 
862 } // namespace SST::Shared
863 
864 #endif // SST_CORE_SHARED_SHAREDARRAY_H
size_t size() const
Get the length of the array.
Definition: sharedArray.h:537
virtual SharedObjectChangeSet * getChangeSet() override
Gets the changeset for this data on this rank.
Definition: sharedArray.h:377
This class is basically a wrapper for objects to declare the order in which their members should be s...
Definition: serializer.h:42
virtual SharedObjectChangeSet * getChangeSet() override
Gets the changeset for this data on this rank.
Definition: sharedArray.h:795
Definition: sharedObject.h:276
const_reverse_iterator rbegin() const
Get const_reverse_iterator to beginning of underlying map.
Definition: sharedArray.h:141
const T & operator[](int index) const
Read data from the array.
Definition: sharedArray.h:203
const_iterator begin() const
Get const_iterator to beginning of underlying map.
Definition: sharedArray.h:549
virtual void resetChangeSet() override
Resets the changeset for this data on this rank.
Definition: sharedArray.h:796
void lock()
Called by the core when writing to shared regions is no longer allowed.
Definition: sharedObject.h:192
bool isFullyPublished()
Checks to see if all instances of this SharedObject have called publish().
Definition: sharedObject.h:115
void publish()
Indicate that the calling element has written all the data it plans to write.
Definition: sharedArray.h:153
size_t size() const
Get the length of the array.
Definition: sharedArray.h:119
SharedArray()
Default constructor for SharedArray.
Definition: sharedArray.h:457
const_reverse_iterator rend() const
Get const_reverse_iterator to end of underlying map.
Definition: sharedArray.h:146
bool empty() const
Tests if array is empty.
Definition: sharedArray.h:544
verify_type
Enum of verify types.
Definition: sharedObject.h:283
bool empty() const
Tests if array is empty.
Definition: sharedArray.h:126
SharedArray class.
Definition: sharedArray.h:448
void write(int index, const T &value)
Write data to the array.
Definition: sharedArray.h:177
int initialize(const std::string &obj_name, size_t length=0, bool init_value=false, verify_type v_type=INIT_VERIFY)
Initialize the SharedArray.
Definition: sharedArray.h:504
Definition: sharedArray.h:24
const_iterator begin() const
Get const_iterator to beginning of underlying map.
Definition: sharedArray.h:131
void write(int index, bool value)
Write data to the array.
Definition: sharedArray.h:595
bool isFullyPublished()
Check whether all instances of this SharedArray have called publish().
Definition: sharedArray.h:167
void setSize(size_t size, bool init_data, verify_type v_type)
Set the size of the array.
Definition: sharedArray.h:710
virtual void resetChangeSet() override
Resets the changeset for this data on this rank.
Definition: sharedArray.h:378
const_reverse_iterator rend() const
Get const_reverse_iterator to end of underlying map.
Definition: sharedArray.h:564
bool mutex_read(int index) const
Read data from the array.
Definition: sharedArray.h:632
SharedArray()
Default constructor for SharedArray.
Definition: sharedArray.h:42
const_reverse_iterator rbegin() const
Get const_reverse_iterator to beginning of underlying map.
Definition: sharedArray.h:559
void publish()
Indicate that the calling element has written all the data it plans to write.
Definition: sharedArray.h:571
const_iterator end() const
Get const_iterator to end of underlying map.
Definition: sharedArray.h:554
SharedArray class.
Definition: sharedArray.h:31
Definition: sharedArray.h:251
~SharedArray()
Shared Array Destructor.
Definition: sharedArray.h:466
~SharedArray()
Shared Array Destructor.
Definition: sharedArray.h:51
int initialize(const std::string &obj_name, size_t length=0, T init_value=T(), verify_type v_type=INIT_VERIFY)
Initialize the SharedArray.
Definition: sharedArray.h:89
const std::string & getName()
Get the name of the SharedObject for this data.
Definition: sharedObject.h:105
This is the base class for holding data on changes made to the shared data on each rank...
Definition: sharedObject.h:48
const T & mutex_read(int index) const
Read data from the array.
Definition: sharedArray.h:214
const_iterator end() const
Get const_iterator to end of underlying map.
Definition: sharedArray.h:136
Base class for holding SharedObject data.
Definition: sharedObject.h:93
bool isFullyPublished()
Check whether all instances of this SharedArray have called publish().
Definition: sharedArray.h:585
bool operator[](int index) const
Read data from the array.
Definition: sharedArray.h:621
void setSize(size_t size, const T &init_data, verify_type v_type)
Set the size of the array.
Definition: sharedArray.h:292