#if !defined(phmap_dump_h_guard_) #define phmap_dump_h_guard_ // --------------------------------------------------------------------------- // Copyright (c) 2019, Gregory Popovitch - greg7mdp@gmail.com // // providing dump/load/mmap_load // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // --------------------------------------------------------------------------- #include #include #include #include "phmap.h" namespace phmap { namespace type_traits_internal { #if defined(__GLIBCXX__) && __GLIBCXX__ < 20150801 template struct IsTriviallyCopyable : public std::integral_constant {}; #else template struct IsTriviallyCopyable : public std::is_trivially_copyable {}; #endif template struct IsTriviallyCopyable> { static constexpr bool value = IsTriviallyCopyable::value && IsTriviallyCopyable::value; }; } namespace priv { // ------------------------------------------------------------------------ // dump/load for raw_hash_set // ------------------------------------------------------------------------ template template bool raw_hash_set::dump(OutputArchive& ar) const { static_assert(type_traits_internal::IsTriviallyCopyable::value, "value_type should be trivially copyable"); if (!ar.dump(size_)) { std::cerr << "Failed to dump size_" << std::endl; return false; } if (size_ == 0) { return true; } if (!ar.dump(capacity_)) { std::cerr << "Failed to dump capacity_" << std::endl; return false; } if (!ar.dump(reinterpret_cast(ctrl_), sizeof(ctrl_t) * (capacity_ + Group::kWidth + 1))) { std::cerr << "Failed to dump ctrl_" << std::endl; return false; } if (!ar.dump(reinterpret_cast(slots_), sizeof(slot_type) * capacity_)) { std::cerr << "Failed to dump slot_" << std::endl; return false; } return true; } template template bool raw_hash_set::load(InputArchive& ar) { static_assert(type_traits_internal::IsTriviallyCopyable::value, "value_type should be trivially copyable"); raw_hash_set().swap(*this); // clear any existing content if (!ar.load(&size_)) { std::cerr << "Failed to load size_" << std::endl; return false; } if (size_ == 0) { return true; } if (!ar.load(&capacity_)) { std::cerr << "Failed to load capacity_" << std::endl; return false; } // allocate memory for ctrl_ and slots_ initialize_slots(); if (!ar.load(reinterpret_cast(ctrl_), sizeof(ctrl_t) * (capacity_ + Group::kWidth + 1))) { std::cerr << "Failed to load ctrl" << std::endl; return false; } if (!ar.load(reinterpret_cast(slots_), sizeof(slot_type) * capacity_)) { std::cerr << "Failed to load slot" << std::endl; return false; } return true; } // ------------------------------------------------------------------------ // dump/load for parallel_hash_set // ------------------------------------------------------------------------ template class RefSet, class Mtx_, class Policy, class Hash, class Eq, class Alloc> template bool parallel_hash_set::dump(OutputArchive& ar) const { static_assert(type_traits_internal::IsTriviallyCopyable::value, "value_type should be trivially copyable"); if (! ar.dump(subcnt())) { std::cerr << "Failed to dump meta!" << std::endl; return false; } for (size_t i = 0; i < sets_.size(); ++i) { auto& inner = sets_[i]; typename Lockable::UniqueLock m(const_cast(inner)); if (!inner.set_.dump(ar)) { std::cerr << "Failed to dump submap " << i << std::endl; return false; } } return true; } template class RefSet, class Mtx_, class Policy, class Hash, class Eq, class Alloc> template bool parallel_hash_set::load(InputArchive& ar) { static_assert(type_traits_internal::IsTriviallyCopyable::value, "value_type should be trivially copyable"); size_t submap_count = 0; if (!ar.load(&submap_count)) { std::cerr << "Failed to load submap count!" << std::endl; return false; } if (submap_count != subcnt()) { std::cerr << "submap count(" << submap_count << ") != N(" << N << ")" << std::endl; return false; } for (size_t i = 0; i < submap_count; ++i) { auto& inner = sets_[i]; typename Lockable::UniqueLock m(const_cast(inner)); if (!inner.set_.load(ar)) { std::cerr << "Failed to load submap " << i << std::endl; return false; } } return true; } } // namespace priv // ------------------------------------------------------------------------ // BinaryArchive // File is closed when archive object is destroyed // ------------------------------------------------------------------------ // ------------------------------------------------------------------------ // ------------------------------------------------------------------------ class BinaryOutputArchive { public: BinaryOutputArchive(const char *file_path) { ofs_.open(file_path, std::ios_base::binary); } bool dump(const char *p, size_t sz) { ofs_.write(p, sz); return true; } template typename std::enable_if::value, bool>::type dump(const V& v) { ofs_.write(reinterpret_cast(&v), sizeof(V)); return true; } private: std::ofstream ofs_; }; class BinaryInputArchive { public: BinaryInputArchive(const char * file_path) { ifs_.open(file_path, std::ios_base::binary); } bool load(char* p, size_t sz) { ifs_.read(p, sz); return true; } template typename std::enable_if::value, bool>::type load(V* v) { ifs_.read(reinterpret_cast(v), sizeof(V)); return true; } private: std::ifstream ifs_; }; } // namespace phmap #endif // phmap_dump_h_guard_