59acbaa67ec7c44138f8957889060c9cfb5e9c7c
[alexxy/gromacs.git] / api / gmxapi / cpp / context_impl.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35 #ifndef GMXAPI_CONTEXT_IMPL_H
36 #define GMXAPI_CONTEXT_IMPL_H
37 /*! \file
38  * \brief Declare gmxapi::ContextImpl
39  *
40  * \author M. Eric Irrgang <ericirrgang@gmail.com>
41  * \ingroup gmxapi
42  */
43
44 #include <memory>
45 #include <string>
46
47 #include "gromacs/mdrun/legacymdrunoptions.h"
48 #include "gromacs/mdtypes/mdrunoptions.h"
49
50 #include "gmxapi/context.h"
51 #include "gmxapi/session.h"
52
53 namespace gmxapi
54 {
55
56 /*!
57  * \brief Provide RAII management of communications resource state.
58  *
59  * To acquire an MpiContextManager is to have assurance that any external MPI
60  * environment is ready to use. When the MpiContextManager is released or
61  * goes out of scope, the destructor finalizes the resources.
62  *
63  * Note that thread-MPI chooses the number of ranks and constructs its
64  * MPI communicator internally, so does not and is unlikely to ever
65  * participate here.
66  *
67  * \todo There is no resource for logging or reporting errors during initialization
68  *
69  * \ingroup gmxapi
70  */
71 class MpiContextManager
72 {
73 public:
74     MpiContextManager();
75
76     ~MpiContextManager();
77
78     /*!
79      * \brief Exclusive ownership of a scoped context means copying is impossible.
80      *
81      * \{
82      */
83     MpiContextManager(const MpiContextManager&) = delete;
84     MpiContextManager& operator=(const MpiContextManager&) = delete;
85     //! \}
86
87     /*!
88      * \brief Move semantics are non-trivial.
89      *
90      * \{
91      */
92     MpiContextManager(MpiContextManager&&) noexcept = delete;
93     MpiContextManager& operator=(MpiContextManager&&) noexcept = delete;
94     //! \}
95 };
96
97 /*!
98  * \brief Context implementation.
99  *
100  * Execution contexts have a uniform interface specified by the API. Implementations for
101  * particular execution environments can specialize / derive from this base.
102  *
103  * \todo Separate interface and implementation.
104  *
105  * \warning Definition and semantics depend on configure-time details. For example,
106  *          MPI-enabled libraries always hold a valid MPI communicator via MpiContextManager,
107  *          whereas tMPI and non-MPI builds hold a meaningless MpiContextManager.
108  *
109  * \todo Provide functions or traits for introspection.
110  *
111  * \ingroup gmxapi
112  */
113 class ContextImpl final : public std::enable_shared_from_this<ContextImpl>
114 {
115 public:
116     ~ContextImpl();
117
118     /*!
119      * \brief Factory function
120      *
121      * Since this class provides `shared_from_this`, we need to make sure
122      * that it never exists without a shared_ptr owning it.
123      *
124      * If we can confirm `shared_from_this` is no longer necessary, implementation may change.
125      * \todo: Use registration/deregistration of launched Sessions to log warnings on shutdown
126      *        instead of letting Session keep ContextImpl alive.
127      *
128      * \return ownership of a new object
129      */
130     static std::shared_ptr<ContextImpl> create();
131
132     /*!
133      * \brief Copy disallowed because Session state would become ambiguous.
134      *
135      * The API implementation needs to unambiguously determine
136      * which Sessions and Contexts are associated with each other.
137      * \{
138      */
139     ContextImpl(const ContextImpl&) = delete;
140     ContextImpl& operator=(const ContextImpl&) = delete;
141     //! \}
142
143     /*!
144      * \brief Objects are not trivial to move.
145      *
146      * \todo Implement move semantics. Requires a moveable const MpiContextManager and
147      *       LegacyMdrunOptions members.
148      *
149      * \{
150      */
151     ContextImpl(ContextImpl&&) = delete;
152     ContextImpl& operator=(ContextImpl&&) = delete;
153     //! \}
154
155     /*!
156      * \brief Translate the workflow to the execution context and launch.
157      *
158      * \param work workflow graph
159      * \return ownership of a new session
160      *
161      * \todo This probably makes more sense as a free function, but we need to determine access policies.
162      *
163      * Session is returned with shared_ptr ownership so that Context
164      * can hold a weak_ptr and because Session Resources handles
165      * are still evolving.
166      * \todo Hide lifetime management and ownership from handle object.
167      * We can achieve the necessary aspects of this shared_ptr at a lower level of implementation.
168      * Note also that returned value policies can be implemented in higher level wrappers to ensure
169      * correct object lifetime scope. (See pybind, for instance.)
170      */
171     std::shared_ptr<Session> launch(const Workflow& work);
172
173     /*!
174      * \brief Retain the ability to find a launched session while it exists.
175      *
176      * The client owns the Session launched by a Context, but it is helpful
177      * for the Context to know if it has an active Session associated with it.
178      *
179      * \todo Use registration/deregistration protocol instead.
180      *       Requires logging facility.
181      */
182     std::weak_ptr<Session> session_;
183
184     /*!
185      * \brief mdrun command line arguments.
186      *
187      * Store arguments provided by the client and pass them when launching
188      * a simulation runner. This allows client code to access the same
189      * options as are available to mdrun on the command line while the API
190      * evolves.
191      */
192     MDArgs mdArgs_;
193
194     /*!
195      * \brief Legacy option-handling and set up for mdrun.
196      *
197      * This object should not exist, but is necessary now to introduce
198      * the API in a way that means CLI and API work similarly and do not
199      * duplicate definitions e.g. of command-line options.
200      */
201     gmx::LegacyMdrunOptions options_;
202
203     /*!
204      * \brief Scoped MPI management.
205      *
206      * Part of the ContextImpl invariant establishes a point where MPI initialization status is
207      * known.
208      *
209      * To ensure the MpiContextManager is initialized only once, we use a const member that must
210      * be initialized at construction.
211      */
212     const MpiContextManager mpi_;
213
214 private:
215     /*!
216      * \brief Basic constructor.
217      *
218      * Don't use this. Use create() to get a shared pointer right away.
219      * Otherwise, shared_from_this() is potentially dangerous.
220      */
221     explicit ContextImpl() noexcept(std::is_nothrow_constructible_v<gmx::LegacyMdrunOptions>);
222 };
223
224
225 class CommHandle
226 {
227 public:
228     using commType = MPI_Comm;
229     MPI_Comm communicator{ MPI_COMM_NULL };
230 };
231
232 } // end namespace gmxapi
233 #endif // GMXAPI_CONTEXT_IMPL_H