Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exposes cache #355

Merged
merged 5 commits into from
Jun 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions include/pluginplay/module_manager/module_manager.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright 2024 NWChemEx Community
*
* 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
*
* http://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.
*/

#pragma once
#include <pluginplay/module_manager/module_manager_class.hpp>
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#pragma once
#include <memory>
#include <parallelzone/runtime/runtime_view.hpp>
#include <pluginplay/cache/module_manager_cache.hpp>
#include <pluginplay/module/module_base.hpp>
#include <pluginplay/module/module_class.hpp>
#include <pluginplay/types.hpp>
Expand All @@ -27,7 +28,7 @@ namespace detail_ {
struct ModuleManagerPIMPL;
}

/** @brief Class responsible for manipulating
/** @brief Class responsible for holding and managing modules.
*
*/
class ModuleManager {
Expand All @@ -50,12 +51,19 @@ class ModuleManager {
/// Type of module key container
using key_container_type = std::vector<type::key>;

/// Type of the cache
using cache_type = cache::ModuleManagerCache;

/// Type of a pointer to the cache
using cache_pointer = std::shared_ptr<cache_type>;

///@{
/** @name Ctors and assignment operators
*
*/
ModuleManager();
ModuleManager(runtime_ptr runtime);
ModuleManager(runtime_ptr runtime,
cache_pointer cache = std::make_shared<cache_type>());
// ModuleManager(const ModuleManager& rhs);
// ModuleManager& operator=(const ModuleManager& rhs) {
// return *this = std::move(ModuleManager(rhs));
Expand Down Expand Up @@ -242,7 +250,25 @@ class ModuleManager {
*/
key_container_type keys() const;

/** @brief Does *this have a cache set?
*
*
* @return True if *this has a place where it can cache input/result pairs
* and false otherwise.
*
* @throw none No throw guarantee.
*/
bool has_cache() const noexcept;

private:
/** @brief Does *this have a PIMPL?
*
* @return False if pimpl_ is set to a null pointer and true otherwise.
*
* @throw None No throw guarantee.
*/
bool has_pimpl_() const noexcept;

/// Bridges the gap between the set_default and the PIMPL
void set_default_(const std::type_info& type, type::input_map inps,
type::key key);
Expand Down
2 changes: 1 addition & 1 deletion include/pluginplay/plugin/plugin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/

#pragma once
#include <pluginplay/module_manager.hpp>
#include <pluginplay/module_manager/module_manager.hpp>
#include <pluginplay/python/python.hpp>

#define DECLARE_PLUGIN(plugin_name) \
Expand Down
2 changes: 1 addition & 1 deletion include/pluginplay/pluginplay.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
#include <pluginplay/config/config.hpp>
#include <pluginplay/fields/fields.hpp>
#include <pluginplay/module/module.hpp>
#include <pluginplay/module_manager.hpp>
#include <pluginplay/module_manager/module_manager.hpp>
#include <pluginplay/plugin/plugin.hpp>
#include <pluginplay/printing/printing.hpp>
#include <pluginplay/property_type/property_type.hpp>
Expand Down
2 changes: 1 addition & 1 deletion include/pluginplay/printing/document_modules.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#include <string>
#include <vector>

#include <pluginplay/module_manager.hpp>
#include <pluginplay/module_manager/module_manager.hpp>
#include <pluginplay/printing/document_module.hpp>

namespace pluginplay::printing {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,15 @@
*/

#pragma once
#include "../module/detail_/module_pimpl.hpp"
#include "../../module/detail_/module_pimpl.hpp"
#include <memory>
#include <parallelzone/runtime/runtime_view.hpp>
#include <pluginplay/cache/module_manager_cache.hpp>
#include <pluginplay/module/module_base.hpp>
#include <pluginplay/module_manager.hpp>
#include <pluginplay/module_manager/module_manager.hpp>
#include <typeindex>

namespace pluginplay {
namespace detail_ {
namespace pluginplay::detail_ {

/** @brief The class that implements the ModuleManager.
*
Expand All @@ -35,12 +34,15 @@ namespace detail_ {
* that it is easier to test the implementation.
*/
struct ModuleManagerPIMPL {
/// Type *this implements
using module_manager_type = ModuleManager;

///@{
/// Type of a pointer to a module's implemenation
using module_base_ptr = typename ModuleManager::module_base_ptr;
using module_base_ptr = module_manager_type::module_base_ptr;

/// Type of a pointer to a read-only module implementation
using const_module_base_ptr = typename ModuleManager::const_module_base_ptr;
using const_module_base_ptr = module_manager_type::const_module_base_ptr;

/// Type of a map from the module implementation's type to the
/// implementation
Expand All @@ -50,26 +52,35 @@ struct ModuleManagerPIMPL {
using shared_module = std::shared_ptr<Module>;

/// Type of a map holding usable modules
using module_map = utilities::CaseInsensitiveMap<shared_module>;
using module_map = module_manager_type::module_map;

/// Type of a map holding the default module key for a given property type
using default_map = std::map<std::type_index, type::key>;

/// The type of the runtime
using runtime_type = parallelzone::runtime::RuntimeView;
using runtime_type = module_manager_type::runtime_type;

/// A pointer to a runtime
using runtime_ptr = std::shared_ptr<runtime_type>;
using runtime_ptr = module_manager_type::runtime_ptr;

/// Type of the cache
using cache_type = module_manager_type::cache_type;

/// Type of a pointer to the cache
using cache_pointer = module_manager_type::cache_pointer;

/// Type of a map from key to Python implementation
// TODO: remove when a more elegant solution is determined
using py_base_map = std::map<type::key, const_module_base_ptr>;

///@}

ModuleManagerPIMPL(runtime_ptr runtime) : m_runtime_(runtime) {}
ModuleManagerPIMPL() :
ModuleManagerPIMPL(std::make_shared<runtime_type>(),
std::make_shared<cache_type>()) {}

ModuleManagerPIMPL() : m_runtime_(std::make_shared<runtime_type>()) {}
ModuleManagerPIMPL(runtime_ptr runtime, cache_pointer cache) :
m_pcaches(cache), m_runtime_(runtime) {}

/// Makes a deep copy of this instance on the heap
// auto clone() { return std::make_unique<ModuleManagerPIMPL>(*this); }
Expand Down Expand Up @@ -106,43 +117,15 @@ struct ModuleManagerPIMPL {
* @param key The module key for the module to use as the default
*/
void set_default(const std::type_info& type, type::input_map inputs,
type::key key) {
if(!count(key)) m_modules.at(key); // Throws a consistent error
m_defaults[std::type_index(type)] = key;
m_inputs[std::type_index(type)] = std::move(inputs);
}
type::key key);

/** @brief This function actually adds a module to the list of available
* modules.
*
* @param key The key under which the module will be registered.
* @param base The instance containing the algorithm
*/
void add_module(type::key key, module_base_ptr base) {
assert_unique_key_(key);
auto uuid = utility::generate_uuid();
auto internal_cache = m_caches.get_or_make_user_cache(uuid);
base->set_cache(internal_cache);
base->set_runtime(m_runtime_);
base->set_uuid(uuid);
auto module_cache = m_caches.get_or_make_module_cache(key);
std::unique_ptr<ModulePIMPL> pimpl;
if(base->is_python()) {
// This is a hacky patch to allow multiple python modules to be
// added while avoiding the type_index collisions.
// TODO: remove when a more elegant solution is determined
m_py_bases[key] = base;
pimpl =
std::make_unique<ModulePIMPL>(m_py_bases[key], module_cache);
} else {
std::type_index type(base->type());
if(!m_bases.count(type)) m_bases[type] = base;
pimpl = std::make_unique<ModulePIMPL>(m_bases[type], module_cache);
}
auto ptr = std::make_shared<Module>(std::move(pimpl));
ptr->set_name(key);
m_modules.emplace(std::move(key), ptr);
}
void add_module(type::key key, module_base_ptr base);

/** @brief Unloads the specified module.
*
Expand All @@ -165,77 +148,23 @@ struct ModuleManagerPIMPL {
* @param old_key The key for the module to copy
* @param new_key The key under which the new module will live
*/
void copy_module(const type::key& old_key, type::key new_key) {
assert_unique_key_(new_key);
Module mod = m_modules.at(old_key)->unlocked_copy();
auto ptr = std::make_shared<Module>(std::move(mod));
ptr->set_name(new_key);
m_modules.emplace(std::move(new_key), ptr);
}
void copy_module(const type::key& old_key, type::key new_key);

/** @brief Returns a module, filling in all non-set submodules with defaults
* if a ready default exists.
*
* @param key The module you want
* @return A shared_ptr to the requested module
*/
shared_module at(const type::key& key) {
if(!count(key)) {
const std::string msg =
"ModuleManager has no module with key: '" + key + "'";
throw std::out_of_range(msg);
}
auto mod = m_modules.at(key);
// Loop over submodules filling them in from the defaults
for(auto& [k, v] : mod->submods()) {
const auto& type = v.type();
// Only change non-ready submodules
if(!v.ready() && m_defaults.count(type)) {
// Recursive to make sure that that module gets filled in
auto default_mod = at(m_defaults.at(type));
// Only change if the module is also ready
if(default_mod->ready(m_inputs.at(type)))
mod->change_submod(k, default_mod);
}
}
return mod;
}
shared_module at(const type::key& key);

///@{
/** @name Comparison operators
*
* @param rhs
* @return
*/
bool operator==(const ModuleManagerPIMPL& rhs) const {
// Try to get out early
if(m_bases.size() != rhs.m_bases.size()) return false;
if(m_modules.size() != rhs.m_modules.size()) return false;
if(m_defaults.size() != rhs.m_defaults.size()) return false;

// TODO: Remove with the rest of the python hack
if(m_py_bases.size() != rhs.m_py_bases.size()) return false;
for(const auto& [k, v] : rhs.m_py_bases) {
if(!m_py_bases.count(k)) return false;
if(*m_py_bases.at(k) != *v) return false;
}

// Skip checking the values b/c implementations are compared by type
for(const auto& [k, v] : rhs.m_bases) {
if(!m_bases.count(k)) return false;
}

// Need to check the values b/c user may have switched options
for(const auto& [k, v] : rhs.m_modules) {
if(!m_modules.count(k)) return false;
if(*m_modules.at(k) != *v) return false;
}

// Easy since not pointers
if(m_defaults != rhs.m_defaults) return false;

return true;
}
bool operator==(const ModuleManagerPIMPL& rhs) const;

bool operator!=(const ModuleManagerPIMPL& rhs) const {
return !((*this) == rhs);
Expand All @@ -245,12 +174,9 @@ struct ModuleManagerPIMPL {

runtime_type& get_runtime() const { return *m_runtime_; }

ModuleManager::key_container_type keys() const {
ModuleManager::key_container_type keys;
keys.reserve(m_modules.size());
for(const auto& [k, v] : m_modules) keys.push_back(k);
return keys;
}
ModuleManager::key_container_type keys() const;

bool has_cache() const noexcept { return static_cast<bool>(m_pcaches); }
///@}

///@{
Expand All @@ -270,7 +196,7 @@ struct ModuleManagerPIMPL {
py_base_map m_py_bases;

// These are the results of the modules running in the user's states
cache::ModuleManagerCache m_caches;
cache_pointer m_pcaches;

// A map of property types
default_map m_defaults;
Expand All @@ -288,5 +214,6 @@ struct ModuleManagerPIMPL {
}
};

} // namespace detail_
} // namespace pluginplay
} // namespace pluginplay::detail_

#include "module_manager_pimpl.ipp"
Loading
Loading