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
20#pragma once
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"
33#include "ObjectId.hpp"
35#include "packed_variant.hpp"
36
37#include "core/MpiCallbacks.hpp"
38
39#include <utils/Factory.hpp>
40
41#include <boost/mpi/communicator.hpp>
42#include <boost/serialization/utility.hpp>
43
44#include <cstddef>
45#include <memory>
46#include <stdexcept>
47#include <string>
48#include <string_view>
49#include <unordered_map>
50#include <utility>
51
52namespace ScriptInterface {
53
54/**
55 * @brief Global synchronizing context.
56 *
57 * Objects created in this context are synchronized
58 * between multiple MPI ranks. That is, for each instance
59 * created on the head node, a copy is created on all
60 * other ranks. If the original copy is mutated via
61 * @ref notify_set_parameter(), this change is also applied to all the
62 * copies. Calls to @ref notify_call_method() are also propagated to all
63 * ranks. The lifetime of the copies is tied to the original,
64 * if the original copy is destroyed on the head node,
65 * the remote copies are also destroyed.
66 */
67class GlobalContext : public Context {
69
70 /* Instances on this node that are managed by the
71 * head node. */
72 std::unordered_map<ObjectId, ObjectRef> m_local_objects;
73
74 std::shared_ptr<LocalContext> m_node_local_context;
75
76 boost::mpi::communicator const &m_comm;
77 bool m_is_head_node;
78
79 ParallelExceptionHandler m_parallel_exception_handler;
80
81 Communication::CallbackHandle<ObjectId, const std::string &,
82 const PackedMap &>
83 cb_make_handle;
84 Communication::CallbackHandle<ObjectId, const std::string &,
85 const PackedVariant &>
86 cb_set_parameter;
87 Communication::CallbackHandle<ObjectId, std::string const &,
88 PackedMap const &>
89 cb_call_method;
91
92public:
93 GlobalContext(std::shared_ptr<Communication::MpiCallbacks> const &callbacks,
94 std::shared_ptr<LocalContext> node_local_context)
95 : m_local_objects(), m_node_local_context(std::move(node_local_context)),
96 m_comm(callbacks->comm()), m_is_head_node(m_comm.rank() == 0),
97 // NOLINTNEXTLINE(bugprone-throw-keyword-missing)
98 m_parallel_exception_handler(m_comm),
99 cb_make_handle(callbacks,
100 [this](ObjectId id, const std::string &name,
102 make_handle(id, name, parameters);
103 }),
104 cb_set_parameter(callbacks,
105 [this](ObjectId id, std::string const &name,
106 PackedVariant const &value) {
107 set_parameter(id, name, value);
108 }),
109 cb_call_method(callbacks,
110 [this](ObjectId id, std::string const &name,
111 PackedMap const &arguments) {
112 call_method(id, name, arguments);
113 }),
114 cb_delete_handle(callbacks,
115 [this](ObjectId id) { delete_handle(id); }) {}
116
117private:
118 /**
119 * @brief Callback for @c cb_make_handle
120 */
121 void make_handle(ObjectId id, const std::string &name,
122 const PackedMap &parameters);
123 /**
124 * @brief Create remote instances
125 *
126 * @param id Internal identifier of the instance
127 * @param name Class name
128 * @param parameters Constructor parameters.
129 */
130 void remote_make_handle(ObjectId id, const std::string &name,
131 const VariantMap &parameters);
132
133private:
134 /**
135 * @brief Callback for @c cb_set_parameter
136 */
137 void set_parameter(ObjectId id, std::string const &name,
138 PackedVariant const &value);
139
140public:
141 void notify_set_parameter(const ObjectHandle *o, std::string const &name,
142 Variant const &value) override;
143
144private:
145 /**
146 * @brief Callback for @c cb_call_method
147 */
148 void call_method(ObjectId id, std::string const &name,
149 PackedMap const &arguments);
150
151public:
152 void notify_call_method(const ObjectHandle *o, std::string const &name,
153 VariantMap const &arguments) override;
154
155private:
156 /**
157 * @brief Callback for @c cb_delete_handle
158 */
159 void delete_handle(ObjectId id) { m_local_objects.erase(id); }
160
161public:
162 /**
163 * @brief Get a new reference counted instance of a script interface
164 * object by name.
165 *
166 * Remote objects are automatically constructed.
167 */
168 std::shared_ptr<ObjectHandle>
169 make_shared(std::string const &name, const VariantMap &parameters) override;
170
171 std::string_view name(const ObjectHandle *o) const override;
172
173 bool is_head_node() const override { return m_is_head_node; }
174 void parallel_try_catch(std::function<void()> const &cb) const override {
175 m_parallel_exception_handler.parallel_try_catch<std::exception>(cb);
176 }
177 boost::mpi::communicator const &get_comm() const override { return m_comm; }
178};
179} // namespace ScriptInterface
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:53
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::mpi::communicator const & get_comm() const override
std::string_view name(const ObjectHandle *o) const override
GlobalContext(std::shared_ptr< Communication::MpiCallbacks > const &callbacks, std::shared_ptr< LocalContext > node_local_context)
bool is_head_node() const 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.
cudaStream_t stream[1]
CUDA streams for parallel computing on CPU and GPU.
make_recursive_variant< ObjectId > PackedVariant
Packed version of Variant.
std::unordered_map< std::string, Variant > VariantMap
Definition Variant.hpp:133
std::vector< std::pair< std::string, PackedVariant > > PackedMap
make_recursive_variant< ObjectRef > Variant
Possible types for parameters.
Definition Variant.hpp:131
STL namespace.
Strongly typed integer type to hold a unique identifier for a ObjectHandle object,...
Definition ObjectId.hpp:37
Recursive variant implementation.
Definition Variant.hpp:84