Loading [MathJax]/extensions/TeX/AMSmath.js
ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages Concepts
ObjectMap.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2022 The ESPResSo project
3 * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010
4 * Max-Planck-Institute for Polymer Research, Theory Group
5 *
6 * This file is part of ESPResSo.
7 *
8 * ESPResSo is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * ESPResSo is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#pragma once
23
28
29#include <memory>
30#include <string>
31#include <type_traits>
32#include <unordered_map>
33#include <utility>
34
35namespace ScriptInterface {
36/**
37 * @brief Owning map of object handles.
38 *
39 * Mapped elements are cleared from the core during destruction.
40 * Due to how dynamic dispatch works, derived types must mark
41 * @ref erase_in_core as @c final` and call @ref do_destruct in
42 * their virtual destructor. This is to ensure that pure virtual
43 * functions called by @ref clear cannot be executed in a type
44 * derived from the type currently being destructed, since derived
45 * types no longer exist at this point of the destruction sequence.
46 *
47 * @tparam ManagedType Type of the managed objects, needs to be
48 * derived from @ref ObjectHandle
49 */
50template <typename ManagedType, class BaseType = ObjectHandle,
51 class KeyType = int>
52class ObjectMap : public ObjectContainer<ObjectMap, ManagedType, BaseType> {
53public:
55 using Base::add_parameters;
57 using mapped_type = std::shared_ptr<ManagedType>;
58 using container_type = std::unordered_map<key_type, mapped_type>;
59
60private:
61 container_type m_elements;
62 bool dtor_sequence_initiated = false;
63
65 virtual void insert_in_core(key_type const &key,
66 mapped_type const &obj_ptr) = 0;
67 virtual void erase_in_core(key_type const &key) = 0;
68
69protected:
70 void do_destruct() {
71 assert(not dtor_sequence_initiated);
72 clear();
73 dtor_sequence_initiated = true;
74 }
75
76public:
78 add_parameters({
79 {"_objects", AutoParameter::read_only,
80 [this]() { return make_unordered_map_of_variants(m_elements); }},
81 });
82 }
83
84 ~ObjectMap() override { assert(dtor_sequence_initiated); }
85
86 // prevent inheritance of the default implementation
87 void do_construct(VariantMap const &params) override = 0;
88
89 /**
90 * @brief Add an element to the map.
91 *
92 * @param key Identifier of the element to add.
93 * @param element The element to add.
94 */
95 void insert(key_type const &key, mapped_type const &element) {
96 insert_in_core(key, element);
97 m_elements[key] = element;
98 }
99
100 /**
101 * @brief Add an element to the map.
102 * A free key is generated automatically.
103 *
104 * @param element The element to add.
105 */
106 key_type insert(mapped_type const &element) {
107 auto const key = insert_in_core(element);
108 m_elements[key] = element;
109 return key;
110 }
111
112 /**
113 * @brief Removes all occurrences of an element from the map.
114 *
115 * @param key Identifier of the element to remove.
116 */
117 void erase(key_type const &key) {
119 m_elements.erase(key);
120 }
121
122 /**
123 * @brief Map elements.
124 */
125 auto const &elements() const { return m_elements; }
126
127 /**
128 * @brief Clear the map.
129 */
130 void clear() {
131 for (auto const &kv : m_elements) {
132 erase_in_core(kv.first);
133 }
134
135 m_elements.clear();
136 }
137
138protected:
139 Variant do_call_method(std::string const &method,
140 VariantMap const &parameters) override {
141
142 if (method == "insert") {
143 auto obj_ptr = get_value<mapped_type>(parameters.at("object"));
144
145 if (parameters.count("key")) {
146 auto const key = get_key(parameters.at("key"));
148 return none;
149 }
150 return insert(obj_ptr);
151 }
152
153 if (method == "erase") {
154 auto const key = get_key(parameters.at("key"));
155 erase(key);
156 return none;
157 }
158
159 if (method == "get") {
160 auto const key = get_key(parameters.at("key"));
161 return Variant{m_elements.at(key)};
162 }
163
164 if (method == "get_map") {
165 return make_unordered_map_of_variants(m_elements);
166 }
167
168 if (method == "keys") {
169 std::vector<Variant> res;
170 for (auto const &kv : m_elements) {
171 res.push_back(kv.first);
172 }
173 return res;
174 }
175
176 if (method == "clear") {
177 clear();
178 return none;
179 }
180
181 if (method == "size") {
182 return static_cast<int>(m_elements.size());
183 }
184
185 if (method == "empty") {
186 return m_elements.empty();
187 }
188
189 if (method == "contains") {
190 return m_elements.find(get_key(parameters.at("key"))) != m_elements.end();
191 }
192
193 return Base::do_call_method(method, parameters);
194 }
195
197 m_elements = get_value_or<decltype(m_elements)>(params, "_objects", {});
198 for (auto const &[key, element] : m_elements) {
199 insert_in_core(key, element);
200 }
201 }
202
203 key_type get_key(Variant const &key) const {
204 try {
205 return get_value<key_type>(key);
206 } catch (...) {
207 using namespace detail::demangle;
208 auto const actual = simplify_symbol_variant(key);
209 auto const target = simplify_symbol(static_cast<key_type *>(nullptr));
210 if (Base::context()->is_head_node()) {
211 throw std::invalid_argument("Key has to be of type '" + target +
212 "', got type '" + actual + "'");
213 }
214 throw;
215 }
216 }
217};
218} // Namespace ScriptInterface
Owning map of object handles.
Definition ObjectMap.hpp:52
std::shared_ptr< ManagedType > mapped_type
Definition ObjectMap.hpp:57
virtual key_type insert_in_core(mapped_type const &obj_ptr)=0
virtual void erase_in_core(key_type const &key)=0
ObjectContainer< ObjectMap, ManagedType, BaseType > Base
Definition ObjectMap.hpp:54
void clear()
Clear the map.
key_type get_key(Variant const &key) const
void erase(key_type const &key)
Removes all occurrences of an element from the map.
std::unordered_map< key_type, mapped_type > container_type
Definition ObjectMap.hpp:58
void do_construct(VariantMap const &params) override=0
auto const & elements() const
Map elements.
virtual void insert_in_core(key_type const &key, mapped_type const &obj_ptr)=0
void restore_from_checkpoint(VariantMap const &params)
key_type insert(mapped_type const &element)
Add an element to the map.
Variant do_call_method(std::string const &method, VariantMap const &parameters) override
void insert(key_type const &key, mapped_type const &element)
Add an element to the map.
Definition ObjectMap.hpp:95
T get_value(Variant const &v)
Extract value of specific type T from a Variant.
std::unordered_map< std::string, Variant > VariantMap
Definition Variant.hpp:69
auto make_unordered_map_of_variants(std::unordered_map< K, V > const &v)
Definition Variant.hpp:80
std::conditional_t< std::is_same_v< BaseType, ObjectHandle >, AutoParameters< Container< ManagedType, BaseType >, BaseType >, BaseType > ObjectContainer
Base class for containers whose BaseType might be a full specialization of AutoParameters.
boost::make_recursive_variant< None, bool, int, std::size_t, double, std::string, ObjectRef, Utils::Vector3b, Utils::Vector3i, Utils::Vector2d, Utils::Vector3d, Utils::Vector4d, std::vector< int >, std::vector< double >, std::vector< boost::recursive_variant_ >, std::unordered_map< int, boost::recursive_variant_ >, std::unordered_map< std::string, boost::recursive_variant_ > >::type Variant
Possible types for parameters.
Definition Variant.hpp:67
constexpr const None none
None-"literal".
Definition Variant.hpp:50
static SteepestDescentParameters params
Currently active steepest descent instance.
static constexpr const ReadOnly read_only