Skip to content

Commit d896528

Browse files
authored
Support ObjectMap for std::bitset<N>, std::vector<bool> and std::atomic<T> (#1483)
1 parent 1d077a7 commit d896528

File tree

6 files changed

+171
-85
lines changed

6 files changed

+171
-85
lines changed

src/sst/core/serialization/impl/serialize_atomic.h

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,32 +26,52 @@ namespace SST::Core::Serialization {
2626
template <class T>
2727
class serialize_impl<std::atomic<T>>
2828
{
29+
// Proxy class which represents a reference to std::atomic<T>, is copyable, convertible to T, and assignable from T
30+
//
31+
// This is only used in mapping mode
32+
class atomic_reference
33+
{
34+
std::atomic<T>& ref;
35+
36+
public:
37+
explicit atomic_reference(std::atomic<T>& ref) :
38+
ref(ref)
39+
{}
40+
41+
// Set the referenced atomic to a value
42+
atomic_reference& operator=(const T& value)
43+
{
44+
ref.store(value);
45+
return *this;
46+
}
47+
48+
// Convert the referenced atomic to its value
49+
operator T() const { return ref.load(); }
50+
};
51+
2952
void operator()(std::atomic<T>& v, serializer& ser, ser_opt_t UNUSED(options))
3053
{
3154
switch ( ser.mode() ) {
3255
case serializer::SIZER:
33-
{
34-
T t = v.load();
35-
SST_SER(t);
36-
// ser.size(t);
37-
break;
38-
}
3956
case serializer::PACK:
4057
{
41-
T t = v.load();
42-
SST_SER(t);
58+
T value { v.load() };
59+
SST_SER(value);
4360
break;
4461
}
4562
case serializer::UNPACK:
4663
{
47-
T val {};
48-
SST_SER(val);
49-
v.store(val);
64+
T value {};
65+
SST_SER(value);
66+
v.store(value);
5067
break;
5168
}
5269
case serializer::MAP:
5370
{
54-
// TODO: Add support for mapping mode
71+
// Create an ObjectMapFundamentalReference referring to a atomic_reference proxy wrapper class
72+
ser.mapper().map_hierarchy_start(ser.getMapName(),
73+
new ObjectMapFundamentalReference<T, atomic_reference, std::atomic<T>>(atomic_reference(v)));
74+
ser.mapper().map_hierarchy_end();
5575
break;
5676
}
5777
}

src/sst/core/serialization/impl/serialize_bitset.h

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,45 +21,62 @@
2121

2222
#include <bitset>
2323
#include <cstddef>
24-
#include <type_traits>
2524

2625
namespace SST::Core::Serialization {
2726

28-
// Serialize std::bitset
27+
// Serialize std::bitset<N>
2928
template <size_t N>
3029
class serialize_impl<std::bitset<N>>
3130
{
32-
using T = std::bitset<N>;
33-
void operator()(T& t, serializer& ser, ser_opt_t UNUSED(options))
31+
void operator()(std::bitset<N>& t, serializer& ser, ser_opt_t UNUSED(options))
3432
{
3533
switch ( ser.mode() ) {
3634
case serializer::MAP:
3735
{
38-
// TODO: Should this be mapped as an array? It will have the same problems as std::vector<bool>
36+
ser.mapper().map_hierarchy_start(ser.getMapName(), new ObjectMapContainer<std::bitset<N>>(&t));
37+
38+
// Serialize reference wrappers to each bit
39+
for ( size_t i = 0; i < N; ++i )
40+
SST_SER_NAME(pvt::bit_reference_wrapper<std::bitset<N>>(t[i]), std::to_string(i).c_str());
41+
42+
ser.mapper().map_hierarchy_end();
3943
break;
4044
}
4145

4246
default:
43-
static_assert(std::is_trivially_copyable_v<T> && std::is_standard_layout_v<T>);
4447
ser.primitive(t);
4548
break;
4649
}
4750
}
4851
SST_FRIEND_SERIALIZE();
4952
};
5053

54+
// Serialize std::bitset<N>*
5155
template <size_t N>
5256
class serialize_impl<std::bitset<N>*>
5357
{
54-
using T = std::bitset<N>;
55-
void operator()(T*& t, serializer& ser, ser_opt_t UNUSED(options))
58+
void operator()(std::bitset<N>*& t, serializer& ser, ser_opt_t UNUSED(options))
5659
{
57-
if ( ser.mode() == serializer::UNPACK ) t = new T {};
60+
if ( ser.mode() == serializer::UNPACK ) t = new std::bitset<N>;
5861
SST_SER(*t);
5962
}
6063
SST_FRIEND_SERIALIZE();
6164
};
6265

66+
// Serialize a std::bitset<N> bit using the pvt::bit_reference_wrapper<std::bitset<N>>
67+
// This is only used in mapping mode
68+
template <size_t N>
69+
class serialize_impl<pvt::bit_reference_wrapper<std::bitset<N>>>
70+
{
71+
void operator()(pvt::bit_reference_wrapper<std::bitset<N>>& t, serializer& ser, ser_opt_t UNUSED(options))
72+
{
73+
ser.mapper().map_hierarchy_start(
74+
ser.getMapName(), new ObjectMapFundamentalReference<bool, typename std::bitset<N>::reference>(t.ref));
75+
ser.mapper().map_hierarchy_end();
76+
}
77+
SST_FRIEND_SERIALIZE();
78+
};
79+
6380
} // namespace SST::Core::Serialization
6481

6582
#endif // SST_CORE_SERIALIZATION_IMPL_SERIALIZE_BITSET_H

src/sst/core/serialization/impl/serialize_insertable.h

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -228,18 +228,18 @@ class serialize_impl<OBJ, std::enable_if_t<is_insertable_v<OBJ>>>
228228

229229
case serializer::MAP:
230230
{
231-
using SST::Core::to_string;
232231
const std::string& name = ser.getMapName();
233232
ser.mapper().map_hierarchy_start(name, new ObjectMapContainer<OBJ>(&obj));
234233

235234
if constexpr ( is_vector_bool_v<OBJ> ) {
236235
// std::vector<bool>
237-
size_t i = 0;
238-
for ( bool e : obj )
239-
SST_SER_NAME(e, to_string(i++).c_str());
236+
// Serialize reference wrappers to each bit.
237+
for ( size_t i = 0; i < obj.size(); ++i )
238+
SST_SER_NAME(pvt::bit_reference_wrapper<OBJ>(obj[i]), std::to_string(i).c_str());
240239
}
241240
else if constexpr ( is_simple_map_v<OBJ> ) {
242241
// non-multi maps with a simple key
242+
using SST::Core::to_string;
243243
for ( auto& [key, value] : obj )
244244
SST_SER_NAME(value, to_string(key).c_str());
245245
}
@@ -251,7 +251,7 @@ class serialize_impl<OBJ, std::enable_if_t<is_insertable_v<OBJ>>>
251251
size_t i = 0;
252252
for ( auto& e : obj )
253253
SST_SER_NAME(
254-
const_cast<value_type&>(reinterpret_cast<const value_type&>(e)), to_string(i++).c_str());
254+
const_cast<value_type&>(reinterpret_cast<const value_type&>(e)), std::to_string(i++).c_str());
255255
}
256256
ser.mapper().map_hierarchy_end();
257257
break;
@@ -274,6 +274,21 @@ class serialize_impl<OBJ*, std::enable_if_t<is_insertable_v<OBJ>>>
274274
SST_FRIEND_SERIALIZE();
275275
};
276276

277+
// Serialize a std::vector<bool> bit using the pvt::bit_reference_wrapper<std::vector<bool>>
278+
// This is only used in mapping mode
279+
template <typename ALLOC>
280+
class serialize_impl<pvt::bit_reference_wrapper<std::vector<bool, ALLOC>>>
281+
{
282+
void operator()(pvt::bit_reference_wrapper<std::vector<bool, ALLOC>>& t, serializer& ser, ser_opt_t UNUSED(options))
283+
{
284+
ser.mapper().map_hierarchy_start(ser.getMapName(),
285+
new ObjectMapFundamentalReference<bool, typename std::vector<bool, ALLOC>::reference>(t.ref));
286+
ser.mapper().map_hierarchy_end();
287+
}
288+
SST_FRIEND_SERIALIZE();
289+
};
290+
291+
277292
} // namespace SST::Core::Serialization
278293

279294
#endif // SST_CORE_SERIALIZATION_IMPL_SERIALIZE_INSERTABLE_H

0 commit comments

Comments
 (0)