-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
330 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,13 +5,13 @@ include(FetchContent) | |
# -------------------------------------------------------------------------------- # | ||
# CMake policy | ||
# -------------------------------------------------------------------------------- # | ||
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13") | ||
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13") | ||
cmake_policy(SET CMP0077 NEW) | ||
endif() | ||
endif () | ||
|
||
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.24") | ||
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.24") | ||
cmake_policy(SET CMP0135 NEW) | ||
endif() | ||
endif () | ||
|
||
# -------------------------------------------------------------------------------- # | ||
# Metall general configuration | ||
|
@@ -92,6 +92,7 @@ option(RUN_LARGE_SCALE_TEST "Run large scale tests" OFF) | |
option(RUN_BUILD_AND_TEST_WITH_CI "Perform build and basic test with CI" OFF) | ||
option(BUILD_VERIFICATION "Build verification directory" OFF) | ||
option(USE_SORTED_BIN "Use VM space aware algorithm in the bin directory" OFF) | ||
option(USE_PERROHT_IN_JSON "Use Perroht in the Metall JSON" OFF) | ||
|
||
set(DEFAULT_VM_RESERVE_SIZE "0" CACHE STRING | ||
"Set the default VM reserve size (use the internally defined value if 0 is specified)") | ||
|
@@ -126,11 +127,11 @@ endif () | |
# -------------------------------------------------------------------------------- # | ||
if (INSTALL_HEADER_ONLY) | ||
message(WARNING "INSTALL_HEADER_ONLY option has been replaced with JUST_INSTALL_METALL_HEADER.") | ||
endif() | ||
endif () | ||
|
||
if (JUST_INSTALL_METALL_HEADER) | ||
return() | ||
endif() | ||
endif () | ||
# -------------------------------------------------------------------------------- # | ||
|
||
# -------------------------------------------------------------------------------- # | ||
|
@@ -211,6 +212,11 @@ if (USE_ANONYMOUS_NEW_MAP) | |
message(STATUS "Use the anonymous map for new map region") | ||
endif () | ||
|
||
if (USE_PERROHT_IN_JSON) | ||
list(APPEND METALL_DEFS "METALL_USE_PERROHT_IN_JSON") | ||
message(STATUS "Use Perroht in the Metall JSON") | ||
endif () | ||
|
||
# Requirements for GCC | ||
if (NOT RUN_BUILD_AND_TEST_WITH_CI) | ||
if (("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")) | ||
|
@@ -259,6 +265,21 @@ if (NOT Boost_FOUND) | |
find_package(Boost 1.64) | ||
endif () | ||
|
||
|
||
# ---------- Perroht ---------- # | ||
if (USE_PERROHT_IN_JSON) | ||
find_package(Perroht QUIET) | ||
if (NOT Perroht_FOUND) | ||
set(JUST_INSTALL_PERROHT_HEADER TRUE) | ||
FetchContent_Declare(Perroht | ||
GIT_REPOSITORY [email protected]:LLNL/Perroht.git | ||
GIT_TAG develop | ||
) | ||
FetchContent_MakeAvailable(Perroht) | ||
endif () | ||
endif () | ||
|
||
|
||
# -------------------------------------------------------------------------------- # | ||
# Add executable functions | ||
# -------------------------------------------------------------------------------- # | ||
|
@@ -304,20 +325,20 @@ function(common_setup_for_metall_executable name) | |
# -------------------- | ||
|
||
# ----- Compile Definitions ----- # | ||
foreach(X IN LISTS METALL_DEFS) | ||
foreach (X IN LISTS METALL_DEFS) | ||
target_compile_definitions(${name} PRIVATE ${X}) | ||
endforeach() | ||
endforeach () | ||
# -------------------- | ||
|
||
# ----- CXX17 Filesystem Lib----- # | ||
# include_cxx_filesystem_library module must be executed first | ||
if (FOUND_CXX17_FILESYSTEM_LIB) | ||
if (REQUIRE_LIB_STDCXX_FS) | ||
target_link_libraries(${name} PRIVATE stdc++fs) | ||
endif() | ||
elseif() | ||
endif () | ||
elseif () | ||
target_compile_definitions(${name} PRIVATE "METALL_DISABLE_CXX17_FILESYSTEM_LIB") | ||
endif() | ||
endif () | ||
# -------------------- | ||
|
||
# ----- Umap----- # | ||
|
@@ -329,6 +350,12 @@ function(common_setup_for_metall_executable name) | |
endif () | ||
endif () | ||
# -------------------- | ||
|
||
# ----- Perroht----- # | ||
if (USE_PERROHT_IN_JSON) | ||
target_link_libraries(${name} PRIVATE Perroht::Perroht) | ||
endif () | ||
# -------------------- | ||
endfunction() | ||
|
||
function(add_metall_executable name source) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,278 @@ | ||
// Copyright 2023 Lawrence Livermore National Security, LLC and other Metall | ||
// Project Developers. See the top-level COPYRIGHT file for details. | ||
// | ||
// SPDX-License-Identifier: (Apache-2.0 OR MIT) | ||
|
||
#ifndef METALL_CONTAINER_EXPERIMENT_JSON_DETAILS_PERROHT_OBJECT_HPP | ||
#define METALL_CONTAINER_EXPERIMENT_JSON_DETAILS_PERROHT_OBJECT_HPP | ||
|
||
#include <iostream> | ||
#include <memory> | ||
#include <utility> | ||
#include <string_view> | ||
#include <algorithm> | ||
|
||
#ifdef METALL_USE_PERROHT_IN_JSON | ||
#include <perroht/unordered_set.hpp> | ||
#include <perroht/utilities/hash.hpp> | ||
#include <perroht/utilities/equal.hpp> | ||
#endif | ||
|
||
#include <metall/json/json_fwd.hpp> | ||
#include <metall/container/scoped_allocator.hpp> | ||
#include <metall/container/vector.hpp> | ||
#include <metall/utility/hash.hpp> | ||
|
||
namespace metall::json::jsndtl { | ||
|
||
namespace { | ||
namespace mc = metall::container; | ||
} | ||
|
||
// Forward declarations | ||
template <typename Alloc = std::allocator<std::byte>> | ||
class perroht_object; | ||
|
||
template <typename allocator_type, typename other_object_type> | ||
bool general_perroht_object_equal( | ||
const perroht_object<allocator_type> &object, | ||
const other_object_type &other_object) noexcept; | ||
|
||
/// \brief JSON object implementation. | ||
/// This class is designed to use a small amount of memory even sacrificing the | ||
/// look-up performance. | ||
template <typename Alloc> | ||
class perroht_object { | ||
public: | ||
using allocator_type = Alloc; | ||
using value_type = | ||
key_value_pair<char, std::char_traits<char>, allocator_type>; | ||
using key_type = std::basic_string_view< | ||
char, std::char_traits<char>>; // typename value_type::key_type; | ||
using mapped_type = value<allocator_type>; // typename | ||
// value_type::value_type; | ||
|
||
private: | ||
template <typename alloc, typename T> | ||
using other_scoped_allocator = mc::scoped_allocator_adaptor< | ||
typename std::allocator_traits<alloc>::template rebind_alloc<T>>; | ||
|
||
struct Hasher { | ||
std::size_t operator()(const value_type &value) const noexcept { | ||
return perroht::StringHash{}(value.key()); | ||
} | ||
std::size_t operator()(const key_type &key) const noexcept { | ||
return perroht::StringHash{}(key); | ||
} | ||
}; | ||
|
||
struct Equal { | ||
bool operator()(const value_type &lhs, | ||
const value_type &rhs) const noexcept { | ||
return perroht::StringEqual{}(lhs.key(), rhs.key()); | ||
} | ||
bool operator()(const value_type &lhs, const key_type &rhs) const noexcept { | ||
return perroht::StringEqual{}(lhs.key(), rhs); | ||
} | ||
bool operator()(const key_type &lhs, const value_type &rhs) const noexcept { | ||
return perroht::StringEqual{}(lhs, rhs.key()); | ||
} | ||
bool operator()(const key_type &lhs, const key_type &rhs) const noexcept { | ||
return perroht::StringEqual{}(lhs, rhs); | ||
} | ||
}; | ||
using value_storage_alloc_type = | ||
other_scoped_allocator<allocator_type, value_type>; | ||
using value_storage_type = | ||
perroht::unordered_flat_set<value_type, Hasher, Equal, | ||
value_storage_alloc_type>; | ||
|
||
// Value: the position of the corresponding item in the value_storage | ||
using value_postion_type = typename value_storage_type::size_type; | ||
|
||
public: | ||
using iterator = typename value_storage_type::iterator; | ||
using const_iterator = typename value_storage_type::const_iterator; | ||
|
||
/// \brief Constructor. | ||
perroht_object() {} | ||
|
||
/// \brief Constructor. | ||
/// \param alloc An allocator object. | ||
explicit perroht_object(const allocator_type &alloc) | ||
: m_value_storage(alloc) {} | ||
|
||
/// \brief Copy constructor | ||
perroht_object(const perroht_object &) = default; | ||
|
||
/// \brief Allocator-extended copy constructor | ||
perroht_object(const perroht_object &other, const allocator_type &alloc) | ||
: m_value_storage(other.m_value_storage, alloc) {} | ||
|
||
/// \brief Move constructor | ||
perroht_object(perroht_object &&) noexcept = default; | ||
|
||
/// \brief Allocator-extended move constructor | ||
perroht_object(perroht_object &&other, const allocator_type &alloc) noexcept | ||
: m_value_storage(std::move(other.m_value_storage), alloc) {} | ||
|
||
/// \brief Copy assignment operator | ||
perroht_object &operator=(const perroht_object &) = default; | ||
|
||
/// \brief Move assignment operator | ||
perroht_object &operator=(perroht_object &&) noexcept = default; | ||
|
||
/// \brief Swap contents. | ||
void swap(perroht_object &other) noexcept { | ||
using std::swap; | ||
swap(m_value_storage, other.m_value_storage); | ||
} | ||
|
||
/// \brief Access a mapped value with a key. | ||
/// If there is no mapped value that is associated with 'key', allocates it | ||
/// first. \param key The key of the mapped value to access. \return A | ||
/// reference to the mapped value associated with 'key'. | ||
mapped_type &operator[](const key_type &key) { | ||
auto itr = find(key); | ||
if (itr != end()) { | ||
return itr->value(); | ||
} | ||
auto ret = m_value_storage.emplace(key, mapped_type{get_allocator()}); | ||
assert(ret.second); | ||
return ret.first->value(); | ||
} | ||
|
||
/// \brief Access a mapped value. | ||
/// \param key The key of the mapped value to access. | ||
/// \return A reference to the mapped value associated with 'key'. | ||
const mapped_type &operator[](const key_type &key) const { | ||
return find(key)->value(); | ||
} | ||
|
||
/// \brief Return true if the key is found. | ||
/// \return True if found; otherwise, false. | ||
bool contains(const key_type &key) const { return count(key) > 0; } | ||
|
||
/// \brief Count the number of elements with a specific key. | ||
/// \return The number elements with a specific key. | ||
std::size_t count(const key_type &key) const { | ||
if (find(key) != end()) { | ||
return 1; | ||
} | ||
return 0; | ||
} | ||
|
||
/// \brief Access a mapped value. | ||
/// \param key The key of the mapped value to access. | ||
/// \return A reference to the mapped value associated with 'key'. | ||
mapped_type &at(const key_type &key) { return find(key)->value(); } | ||
|
||
/// \brief Access a mapped value. | ||
/// \param key The key of the mapped value to access. | ||
/// \return A reference to the mapped value associated with 'key'. | ||
const mapped_type &at(const key_type &key) const { | ||
return find(key)->value(); | ||
} | ||
|
||
iterator find(const key_type &key) { return m_value_storage.find(key); } | ||
|
||
const_iterator find(const key_type &key) const { | ||
return m_value_storage.find(key); | ||
} | ||
|
||
/// \brief Returns an iterator that is at the beginning of the objects. | ||
/// \return An iterator that is at the beginning of the objects. | ||
iterator begin() { return m_value_storage.begin(); } | ||
|
||
/// \brief Returns an iterator that is at the beginning of the objects. | ||
/// \return A const iterator that is at the beginning of the objects. | ||
const_iterator begin() const { return m_value_storage.begin(); } | ||
|
||
/// \brief Returns an iterator that is at the end of the objects. | ||
/// \return An iterator that is at the end of the objects. | ||
iterator end() { return m_value_storage.end(); } | ||
|
||
/// \brief Returns an iterator that is at the end of the objects. | ||
/// \return A const iterator that is at the end of the objects. | ||
const_iterator end() const { return m_value_storage.end(); } | ||
|
||
/// \brief Returns the number of key-value pairs. | ||
/// \return The number of key-values pairs. | ||
std::size_t size() const { return m_value_storage.size(); } | ||
|
||
/// \brief Erases the element at 'position'. | ||
/// \param position The position of the element to erase. | ||
/// \return Iterator following the removed element. | ||
/// If 'position' refers to the last element, then the end() iterator is | ||
/// returned. | ||
iterator erase(iterator position) { return m_value_storage.erase(position); } | ||
|
||
/// \brief Erases the element at 'position'. | ||
/// \param position The position of the element to erase. | ||
/// \return Iterator following the removed element. | ||
/// If 'position' refers to the last element, then the end() iterator is | ||
/// returned. | ||
iterator erase(const_iterator position) { | ||
return m_value_storage.erase(position); | ||
} | ||
|
||
/// \brief Erases the element associated with 'key'. | ||
/// \param key The key of the element to erase. | ||
/// \return Iterator following the removed element. | ||
/// If 'position' refers to the last element, then the end() iterator is | ||
/// returned. | ||
iterator erase(const key_type &key) { | ||
return m_value_storage.erase(find(key)); | ||
} | ||
|
||
/// \brief Return `true` if two objects are equal. | ||
/// \param lhs An object to compare. | ||
/// \param rhs An object to compare. | ||
/// \return True if two objects are equal. Otherwise, false. | ||
friend bool operator==(const perroht_object &lhs, | ||
const perroht_object &rhs) noexcept { | ||
return jsndtl::general_perroht_object_equal(lhs, rhs); | ||
} | ||
|
||
/// \brief Return `true` if two objects are not equal. | ||
/// \param lhs An object to compare. | ||
/// \param rhs An object to compare. | ||
/// \return True if two objects are not equal. Otherwise, false. | ||
friend bool operator!=(const perroht_object &lhs, | ||
const perroht_object &rhs) noexcept { | ||
return !(lhs == rhs); | ||
} | ||
|
||
/// \brief Return an allocator object. | ||
allocator_type get_allocator() const noexcept { | ||
return m_value_storage.get_allocator(); | ||
} | ||
|
||
private: | ||
value_storage_type m_value_storage{allocator_type{}}; | ||
}; | ||
|
||
/// \brief Swap value instances. | ||
template <typename allocator_type> | ||
inline void swap(perroht_object<allocator_type> &lhd, | ||
perroht_object<allocator_type> &rhd) noexcept { | ||
lhd.swap(rhd); | ||
} | ||
|
||
/// \brief Provides 'equal' calculation for other object types that have the | ||
/// same interface as the object class. | ||
template <typename allocator_type, typename other_object_type> | ||
inline bool general_perroht_object_equal( | ||
const perroht_object<allocator_type> &object, | ||
const other_object_type &other_object) noexcept { | ||
return object.size() == other_object.size() && | ||
std::equal(object.begin(), object.end(), other_object.begin(), | ||
other_object.end(), [](const auto &lhs, const auto &rhs) { | ||
return lhs.key() == rhs.key() && | ||
lhs.value() == rhs.value(); | ||
}); | ||
} | ||
|
||
} // namespace metall::json::jsndtl | ||
|
||
#endif // METALL_CONTAINER_EXPERIMENT_JSON_DETAILS_PERROHT_OBJECT_HPP |
Oops, something went wrong.