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