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 <ranges>
31#include <string>
32#include <type_traits>
33#include <unordered_map>
34#include <utility>
35
36namespace ScriptInterface {
37/**
38 * @brief Owning map of object handles.
39 *
40 * Mapped elements are cleared from the core during destruction.
41 * Due to how dynamic dispatch works, derived types must mark
42 * @ref erase_in_core as @c final` and call @ref do_destruct in
43 * their virtual destructor. This is to ensure that pure virtual
44 * functions called by @ref clear cannot be executed in a type
45 * derived from the type currently being destructed, since derived
46 * types no longer exist at this point of the destruction sequence.
47 *
48 * @tparam ManagedType Type of the managed objects, needs to be
49 * derived from @ref ObjectHandle
50 */
51template <typename ManagedType, class BaseType = ObjectHandle,
52 class KeyType = int>
53class ObjectMap : public ObjectContainer<ObjectMap, ManagedType, BaseType> {
54public:
56 using Base::add_parameters;
58 using mapped_type = std::shared_ptr<ManagedType>;
59 using container_type = std::unordered_map<key_type, mapped_type>;
60
61private:
62 container_type m_elements;
63 bool dtor_sequence_initiated = false;
64
66 virtual void insert_in_core(key_type const &key,
67 mapped_type const &obj_ptr) = 0;
68 virtual void erase_in_core(key_type const &key) = 0;
69
70protected:
71 void do_destruct() {
72 assert(not dtor_sequence_initiated);
73 clear();
74 dtor_sequence_initiated = true;
75 }
76
77public:
79 add_parameters({
80 {"_objects", AutoParameter::read_only,
81 [this]() { return make_unordered_map_of_variants(m_elements); }},
82 });
83 }
84
85 ~ObjectMap() override { assert(dtor_sequence_initiated); }
86
87 // prevent inheritance of the default implementation
88 void do_construct(VariantMap const &params) override = 0;
89
90 /**
91 * @brief Add an element to the map.
92 *
93 * @param key Identifier of the element to add.
94 * @param element The element to add.
95 */
96 void insert(key_type const &key, mapped_type const &element) {
97 insert_in_core(key, element);
98 m_elements[key] = element;
99 }
100
101 /**
102 * @brief Add an element to the map.
103 * A free key is generated automatically.
104 *
105 * @param element The element to add.
106 */
107 key_type insert(mapped_type const &element) {
108 auto const key = insert_in_core(element);
109 m_elements[key] = element;
110 return key;
111 }
112
113 /**
114 * @brief Removes all occurrences of an element from the map.
115 *
116 * @param key Identifier of the element to remove.
117 */
118 void erase(key_type const &key) {
120 m_elements.erase(key);
121 }
122
123 /**
124 * @brief Map elements.
125 */
126 auto const &elements() const { return m_elements; }
127
128 /**
129 * @brief Clear the map.
130 */
131 void clear() {
132 for (auto const &key : std::views::elements<0>(m_elements)) {
134 }
135
136 m_elements.clear();
137 }
138
139protected:
140 Variant do_call_method(std::string const &method,
141 VariantMap const &parameters) override {
142
143 if (method == "insert") {
144 auto obj_ptr = get_value<mapped_type>(parameters.at("object"));
145
146 if (parameters.contains("key")) {
147 auto const key = get_key(parameters.at("key"));
149 return none;
150 }
151 return insert(obj_ptr);
152 }
153
154 if (method == "erase") {
155 auto const key = get_key(parameters.at("key"));
156 erase(key);
157 return none;
158 }
159
160 if (method == "get") {
161 auto const key = get_key(parameters.at("key"));
162 return Variant{m_elements.at(key)};
163 }
164
165 if (method == "get_map") {
166 return make_unordered_map_of_variants(m_elements);
167 }
168
169 if (method == "keys") {
170 auto const view = std::views::elements<0>(m_elements);
171 return std::vector<KeyType>{view.begin(), view.end()};
172 }
173
174 if (method == "clear") {
175 clear();
176 return none;
177 }
178
179 if (method == "size") {
180 return static_cast<int>(m_elements.size());
181 }
182
183 if (method == "empty") {
184 return m_elements.empty();
185 }
186
187 if (method == "contains") {
188 return m_elements.find(get_key(parameters.at("key"))) != m_elements.end();
189 }
190
191 return Base::do_call_method(method, parameters);
192 }
193
195 m_elements = get_value_or<decltype(m_elements)>(params, "_objects", {});
196 for (auto const &[key, element] : m_elements) {
197 insert_in_core(key, element);
198 }
199 }
200
201 key_type get_key(Variant const &key) const {
202 try {
203 return get_value<key_type>(key);
204 } catch (...) {
205 using namespace detail::demangle;
206 auto const actual = simplify_symbol_variant(key);
207 auto const target = simplify_symbol(static_cast<key_type *>(nullptr));
208 if (Base::context()->is_head_node()) {
209 throw std::invalid_argument("Key has to be of type '" + target +
210 "', got type '" + actual + "'");
211 }
212 throw;
213 }
214 }
215};
216} // Namespace ScriptInterface
Owning map of object handles.
Definition ObjectMap.hpp:53
std::shared_ptr< ManagedType > mapped_type
Definition ObjectMap.hpp:58
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:55
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:59
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:96
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.
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:133
auto make_unordered_map_of_variants(std::unordered_map< K, V > const &v)
Definition Variant.hpp:144
constexpr const None none
None-"literal".
Definition Variant.hpp:126
static SteepestDescentParameters params
Currently active steepest descent instance.
static constexpr const ReadOnly read_only
Recursive variant implementation.
Definition Variant.hpp:84