]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/mpi/include/boost/mpi/python/skeleton_and_content.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / mpi / include / boost / mpi / python / skeleton_and_content.hpp
CommitLineData
7c673cae
FG
1// (C) Copyright 2006 Douglas Gregor <doug.gregor -at- gmail.com>
2
3// Use, modification and distribution is subject to the Boost Software
4// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
5// http://www.boost.org/LICENSE_1_0.txt)
6
7// Authors: Douglas Gregor
8#ifndef BOOST_MPI_PYTHON_SKELETON_AND_CONTENT_HPP
9#define BOOST_MPI_PYTHON_SKELETON_AND_CONTENT_HPP
10
11/** @file skeleton_and_content.hpp
12 *
13 * This file reflects the skeleton/content facilities into Python.
14 */
15#include <boost/python.hpp>
16#include <boost/mpi.hpp>
17#include <boost/function/function1.hpp>
18#define BOOST_MPI_PYTHON_FORWARD_ONLY
19#include <boost/mpi/python.hpp>
20#include <boost/mpi/python/serialize.hpp>
21
22
23namespace boost { namespace mpi { namespace python {
24
25/**
26 * INTERNAL ONLY
27 *
28 * This @c content class is a wrapper around the C++ "content"
29 * retrieved from get_content. This wrapper is only needed to store a
30 * copy of the Python object on which get_content() was called.
31 */
32class content : public boost::mpi::content
33{
34 typedef boost::mpi::content inherited;
35
36 public:
37 content(const inherited& base, boost::python::object object)
38 : inherited(base), object(object) { }
39
40 inherited& base() { return *this; }
41 const inherited& base() const { return *this; }
42
43 boost::python::object object;
44};
45
46/**
47 * INTERNAL ONLY
48 *
49 * A class specific to the Python bindings that mimics the behavior of
50 * the skeleton_proxy<T> template. In the case of Python skeletons, we
51 * only need to know the object (and its type) to transmit the
52 * skeleton. This is the only user-visible skeleton proxy type,
53 * although instantiations of its derived classes (@c
54 * skeleton_proxy<T>) will be returned from the Python skeleton()
55 * function.
56 */
57class skeleton_proxy_base
58{
59public:
60 skeleton_proxy_base(const boost::python::object& object) : object(object) { }
61
62 boost::python::object object;
63};
64
65/**
66 * INTERNAL ONLY
67 *
68 * The templated @c skeleton_proxy class represents a skeleton proxy
69 * in Python. The only data is stored in the @c skeleton_proxy_base
70 * class (which is the type actually exposed as @c skeleton_proxy in
71 * Python). However, the type of @c skeleton_proxy<T> is important for
72 * (de-)serialization of @c skeleton_proxy<T>'s for transmission.
73 */
74template<typename T>
75class skeleton_proxy : public skeleton_proxy_base
76{
77 public:
78 skeleton_proxy(const boost::python::object& object)
79 : skeleton_proxy_base(object) { }
80};
81
82namespace detail {
83 using boost::python::object;
84 using boost::python::extract;
85
86 extern BOOST_MPI_DECL boost::python::object skeleton_proxy_base_type;
87
88 template<typename T>
89 struct skeleton_saver
90 {
91 void
92 operator()(packed_oarchive& ar, const object& obj, const unsigned int)
93 {
94 packed_skeleton_oarchive pso(ar);
95 pso << extract<T&>(obj.attr("object"))();
96 }
97 };
98
99 template<typename T>
100 struct skeleton_loader
101 {
102 void
103 operator()(packed_iarchive& ar, object& obj, const unsigned int)
104 {
105 packed_skeleton_iarchive psi(ar);
106 extract<skeleton_proxy<T>&> proxy(obj);
107 if (!proxy.check())
108 obj = object(skeleton_proxy<T>(object(T())));
109
110 psi >> extract<T&>(obj.attr("object"))();
111 }
112 };
113
114 /**
115 * The @c skeleton_content_handler structure contains all of the
116 * information required to extract a skeleton and content from a
117 * Python object with a certain C++ type.
118 */
119 struct skeleton_content_handler {
120 function1<object, const object&> get_skeleton_proxy;
121 function1<content, const object&> get_content;
122 };
123
124 /**
125 * A function object that extracts the skeleton from of a Python
126 * object, which is actually a wrapped C++ object of type T.
127 */
128 template<typename T>
129 struct do_get_skeleton_proxy
130 {
131 object operator()(object value) {
132 return object(skeleton_proxy<T>(value));
133 }
134 };
135
136 /**
137 * A function object that extracts the content of a Python object,
138 * which is actually a wrapped C++ object of type T.
139 */
140 template<typename T>
141 struct do_get_content
142 {
143 content operator()(object value_obj) {
144 T& value = extract<T&>(value_obj)();
145 return content(boost::mpi::get_content(value), value_obj);
146 }
147 };
148
149 /**
150 * Determine if a skeleton and content handler for @p type has
151 * already been registered.
152 */
153 BOOST_MPI_PYTHON_DECL bool
154 skeleton_and_content_handler_registered(PyTypeObject* type);
155
156 /**
157 * Register a skeleton/content handler with a particular Python type
158 * (which actually wraps a C++ type).
159 */
160 BOOST_MPI_PYTHON_DECL void
161 register_skeleton_and_content_handler(PyTypeObject*,
162 const skeleton_content_handler&);
163} // end namespace detail
164
165template<typename T>
166void register_skeleton_and_content(const T& value, PyTypeObject* type)
167{
168 using boost::python::detail::direct_serialization_table;
169 using boost::python::detail::get_direct_serialization_table;
170 using namespace boost::python;
171
172 // Determine the type
173 if (!type)
174 type = object(value).ptr()->ob_type;
175
176 // Don't re-register the same type.
177 if (detail::skeleton_and_content_handler_registered(type))
178 return;
179
180 // Register the skeleton proxy type
181 {
182 boost::python::scope proxy_scope(detail::skeleton_proxy_base_type);
183 std::string name("skeleton_proxy<");
184 name += typeid(T).name();
185 name += ">";
186 class_<skeleton_proxy<T>, bases<skeleton_proxy_base> >(name.c_str(),
187 no_init);
188 }
189
190 // Register the saver and loader for the associated skeleton and
191 // proxy, to allow (de-)serialization of skeletons via the proxy.
192 direct_serialization_table<packed_iarchive, packed_oarchive>& table =
193 get_direct_serialization_table<packed_iarchive, packed_oarchive>();
194 table.register_type(detail::skeleton_saver<T>(),
195 detail::skeleton_loader<T>(),
196 skeleton_proxy<T>(object(value)));
197
198 // Register the rest of the skeleton/content mechanism, including
199 // handlers that extract a skeleton proxy from a Python object and
200 // extract the content from a Python object.
201 detail::skeleton_content_handler handler;
202 handler.get_skeleton_proxy = detail::do_get_skeleton_proxy<T>();
203 handler.get_content = detail::do_get_content<T>();
204 detail::register_skeleton_and_content_handler(type, handler);
205}
206
207} } } // end namespace boost::mpi::python
208
209#endif // BOOST_MPI_PYTHON_SKELETON_AND_CONTENT_HPP