Skip to content

Commit

Permalink
Merge pull request #347 from DARMA-tasking/273-add-std-optional-seria…
Browse files Browse the repository at this point in the history
…lizer

#273: add `std::optional` serializer
  • Loading branch information
lifflander authored Jun 11, 2024
2 parents f6cf0af + 2a0ab46 commit b45fbe7
Show file tree
Hide file tree
Showing 4 changed files with 210 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/checkpoint/checkpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
#include "checkpoint/container/unique_ptr_serialize.h"
#include "checkpoint/container/view_serialize.h"
#include "checkpoint/container/variant_serialize.h"
#include "checkpoint/container/optional_serialize.h"

#include "checkpoint/container/kokkos_unordered_map_serialize.h"
#include "checkpoint/container/kokkos_pair_serialize.h"
Expand Down
95 changes: 95 additions & 0 deletions src/checkpoint/container/optional_serialize.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
//@HEADER
// *****************************************************************************
//
// optional_serialize.h
// DARMA/checkpoint => Serialization Library
//
// Copyright 2019 National Technology & Engineering Solutions of Sandia, LLC
// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S.
// Government retains certain rights in this software.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * Neither the name of the copyright holder nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Questions? Contact [email protected]
//
// *****************************************************************************
//@HEADER
*/

#if !defined INCLUDED_CHECKPOINT_CONTAINER_OPTIONAL_SERIALIZE_H
#define INCLUDED_CHECKPOINT_CONTAINER_OPTIONAL_SERIALIZE_H

#include "checkpoint/common.h"

#include <optional>

namespace checkpoint {

template <typename SerializerT, typename T>
void deserializeOptional(SerializerT& s, std::optional<T>& optional) {
using BoolReconstructor =
dispatch::Reconstructor<typename dispatch::CleanType<bool>::CleanT>;
using ValReconstructor =
dispatch::Reconstructor<typename dispatch::CleanType<T>::CleanT>;

dispatch::Allocator<bool> boolAllocated;
dispatch::Allocator<T> valAllocated;

auto* has_value = BoolReconstructor::construct(boolAllocated.buf);
s | *has_value;
if (*has_value) {
auto* value = ValReconstructor::construct(valAllocated.buf);
s | *value;
optional = *value;
} else {
optional.reset();
}
}

template <typename SerializerT, typename T>
void serialize(SerializerT& s, std::optional<T>& optional) {
if (s.isFootprinting()) {
s.countBytes(optional);
if (optional.has_value()) {
s.addBytes(sizeof(*optional));
}
} else if (s.isUnpacking()) {
deserializeOptional(s, optional);
} else {
bool has_value = optional.has_value();

s | has_value;
if (has_value) {
s | *optional;
}
}
}

} /* end namespace checkpoint */

#endif /*INCLUDED_CHECKPOINT_CONTAINER_OPTIONAL_SERIALIZE_H*/
21 changes: 21 additions & 0 deletions tests/unit/test_footprinter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,27 @@ TEST_F(TestFootprinter, test_vector) {
}
}

TEST_F(TestFootprinter, test_optional_footprint) {
{
std::optional<bool> opt = true;
EXPECT_EQ(checkpoint::getMemoryFootprint(opt), sizeof(opt) + sizeof(bool));
opt.reset();
EXPECT_EQ(checkpoint::getMemoryFootprint(opt), sizeof(opt));
}
{
std::optional<long long> opt = 123;
EXPECT_EQ(checkpoint::getMemoryFootprint(opt), sizeof(opt) + sizeof(long long));
opt.reset();
EXPECT_EQ(checkpoint::getMemoryFootprint(opt), sizeof(opt));
}
{
std::optional<std::string> opt = "999";
EXPECT_EQ(checkpoint::getMemoryFootprint(opt), sizeof(opt) + sizeof(std::string("999")));
opt.reset();
EXPECT_EQ(checkpoint::getMemoryFootprint(opt), sizeof(opt));
}
}

TEST_F(TestFootprinter, test_virtual_serialize) {
{
std::unique_ptr<TestBase> ptr = std::make_unique<TestDerived2>(0);
Expand Down
93 changes: 93 additions & 0 deletions tests/unit/test_optional.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
//@HEADER
// *****************************************************************************
//
// test_optional.cc
// DARMA/checkpoint => Serialization Library
//
// Copyright 2019 National Technology & Engineering Solutions of Sandia, LLC
// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S.
// Government retains certain rights in this software.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * Neither the name of the copyright holder nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Questions? Contact [email protected]
//
// *****************************************************************************
//@HEADER
*/

#include <gtest/gtest.h>

#include "test_harness.h"

#include <checkpoint/checkpoint.h>

#include <optional>
#include <string>

namespace checkpoint { namespace tests { namespace unit {

using TestOptional = TestHarness;

template <typename T>
void testOptional(std::optional<T> before) {
// Test serialization when containing the value
{
auto ret = checkpoint::serialize(before);
auto after = checkpoint::deserialize<std::optional<T>>(ret->getBuffer());

EXPECT_TRUE(nullptr != after);
EXPECT_EQ(before.has_value(), after->has_value());
EXPECT_EQ(before, *after);
}

before.reset();

// Test serialization when there is not value
{
auto ret = checkpoint::serialize(before);
auto after = checkpoint::deserialize<std::optional<T>>(ret->getBuffer());

EXPECT_TRUE(nullptr != after);
EXPECT_EQ(before.has_value(), after->has_value());
EXPECT_EQ(before, *after);
}
}

TEST_F(TestOptional, test_optional) {
testOptional<bool>({true});
testOptional<uint8_t>({1});
testOptional<uint16_t>({2});
testOptional<int>({3});
testOptional<long long>({4});
testOptional<float>({5});
testOptional<double>({6});
testOptional<std::string>({"7"});
}

}}} // end namespace checkpoint::tests::unit

0 comments on commit b45fbe7

Please sign in to comment.