ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
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