ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
GlobalContext.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2020-2022 The ESPResSo project
3 *
4 * This file is part of ESPResSo.
5 *
6 * ESPResSo is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * ESPResSo is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19#ifndef ESPRESSO_SCRIPT_INTERFACE_OBJECTMANAGER_HPP
20#define ESPRESSO_SCRIPT_INTERFACE_OBJECTMANAGER_HPP
21
22/** @file
23 *
24 * Infrastructure to synchronize objects created on the head node
25 * with their corresponding remote copies.
26 *
27 * Implementation in @ref GlobalContext.cpp.
28 */
29
30#include "Context.hpp"
31#include "LocalContext.hpp"
32#include "ObjectHandle.hpp"
34#include "packed_variant.hpp"
35
36#include "core/MpiCallbacks.hpp"
37
38#include <utils/Factory.hpp>
39
40#include <boost/mpi/communicator.hpp>
41#include <boost/serialization/utility.hpp>
42
43#include <cstddef>
44#include <memory>
45#include <stdexcept>
46#include <string>
47#include <unordered_map>
48#include <utility>
49
50namespace ScriptInterface {
51
52/**
53 * @brief Global synchronizing context.
54 *
55 * Objects created in this context are synchronized
56 * between multiple MPI ranks. That is, for each instance
57 * created on the head node, a copy is created on all
58 * other ranks. If the original copy is mutated via
59 * @ref notify_set_parameter(), this change is also applied to all the
60 * copies. Calls to @ref notify_call_method() are also propagated to all
61 * ranks. The lifetime of the copies is tied to the original,
62 * if the original copy is destroyed on the head node,
63 * the remote copies are also destroyed.
64 */
65class GlobalContext : public Context {
66 using ObjectId = std::size_t;
67
68 /* Instances on this node that are managed by the
69 * head node. */
70 std::unordered_map<ObjectId, ObjectRef> m_local_objects;
71
72 std::shared_ptr<LocalContext> m_node_local_context;
73
74 boost::mpi::communicator const &m_comm;
75 bool m_is_head_node;
76
77 ParallelExceptionHandler m_parallel_exception_handler;
78
79 Communication::CallbackHandle<ObjectId, const std::string &,
80 const PackedMap &>
81 cb_make_handle;
82 Communication::CallbackHandle<ObjectId, const std::string &,
83 const PackedVariant &>
84 cb_set_parameter;
85 Communication::CallbackHandle<ObjectId, std::string const &,
86 PackedMap const &>
87 cb_call_method;
89
90public:
91 GlobalContext(std::shared_ptr<Communication::MpiCallbacks> const &callbacks,
92 std::shared_ptr<LocalContext> node_local_context)
93 : m_local_objects(), m_node_local_context(std::move(node_local_context)),
94 m_comm(callbacks->comm()), m_is_head_node(m_comm.rank() == 0),
95 // NOLINTNEXTLINE(bugprone-throw-keyword-missing)
96 m_parallel_exception_handler(m_comm),
97 cb_make_handle(callbacks,
98 [this](ObjectId id, const std::string &name,
99 const PackedMap &parameters) {
100 make_handle(id, name, parameters);
101 }),
102 cb_set_parameter(callbacks,
103 [this](ObjectId id, std::string const &name,
104 PackedVariant const &value) {
105 set_parameter(id, name, value);
106 }),
107 cb_call_method(callbacks,
108 [this](ObjectId id, std::string const &name,
109 PackedMap const &arguments) {
110 call_method(id, name, arguments);
111 }),
112 cb_delete_handle(callbacks,
113 [this](ObjectId id) { delete_handle(id); }) {}
114
115private:
116 /**
117 * @brief Callback for @c cb_make_handle
118 */
119 void make_handle(ObjectId id, const std::string &name,
120 const PackedMap &parameters);
121 /**
122 * @brief Create remote instances
123 *
124 * @param id Internal identifier of the instance
125 * @param name Class name
126 * @param parameters Constructor parameters.
127 */
128 void remote_make_handle(ObjectId id, const std::string &name,
129 const VariantMap &parameters);
130
131private:
132 /**
133 * @brief Callback for @c cb_set_parameter
134 */
135 void set_parameter(ObjectId id, std::string const &name,
136 PackedVariant const &value);
137
138public:
139 void notify_set_parameter(const ObjectHandle *o, std::string const &name,
140 Variant const &value) override;
141
142private:
143 /**
144 * @brief Callback for @c cb_call_method
145 */
146 void call_method(ObjectId id, std::string const &name,
147 PackedMap const &arguments);
148
149public:
150 void notify_call_method(const ObjectHandle *o, std::string const &name,
151 VariantMap const &arguments) override;
152
153private:
154 /**
155 * @brief Callback for @c cb_delete_handle
156 */
157 void delete_handle(ObjectId id) { m_local_objects.erase(id); }
158
159public:
160 /**
161 * @brief Get a new reference counted instance of a script interface
162 * object by name.
163 *
164 * Remote objects are automatically constructed.
165 */
166 std::shared_ptr<ObjectHandle>
167 make_shared(std::string const &name, const VariantMap &parameters) override;
168 std::shared_ptr<ObjectHandle>
169 make_shared_local(std::string const &name,
170 VariantMap const &parameters) override;
171
172 boost::string_ref name(const ObjectHandle *o) const override;
173
174 bool is_head_node() const override { return m_is_head_node; }
175 void parallel_try_catch(std::function<void()> const &cb) const override {
176 m_parallel_exception_handler.parallel_try_catch<std::exception>(cb);
177 }
178 boost::mpi::communicator const &get_comm() const override { return m_comm; }
179};
180} // namespace ScriptInterface
181
182#endif
ScriptInterface::Context decorates ScriptInterface::ObjectHandle objects with a context: a creation p...
Communication::MpiCallbacks manages MPI communication using a visitor pattern.
Context of an object handle.
Definition Context.hpp:54
Global synchronizing context.
std::shared_ptr< ObjectHandle > make_shared(std::string const &name, const VariantMap &parameters) override
Get a new reference counted instance of a script interface object by name.
void notify_set_parameter(const ObjectHandle *o, std::string const &name, Variant const &value) override
boost::string_ref name(const ObjectHandle *o) const override
boost::mpi::communicator const & get_comm() const override
GlobalContext(std::shared_ptr< Communication::MpiCallbacks > const &callbacks, std::shared_ptr< LocalContext > node_local_context)
bool is_head_node() const override
std::shared_ptr< ObjectHandle > make_shared_local(std::string const &name, VariantMap const &parameters) override
void parallel_try_catch(std::function< void()> const &cb) const override
void notify_call_method(const ObjectHandle *o, std::string const &name, VariantMap const &arguments) override
Handle exceptions thrown in MPI parallel code.
void parallel_try_catch(std::function< void()> const &callback) const
Handle exceptions in synchronous code.
std::unordered_map< std::string, Variant > VariantMap
Definition Variant.hpp:69
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
std::vector< std::pair< std::string, PackedVariant > > PackedMap
std::size_t ObjectId
boost::make_recursive_variant< None, bool, int, std::size_t, double, std::string, ObjectId, 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 PackedVariant
Packed version of Variant.