File indexing completed on 2025-01-18 09:40:57
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #ifndef BOOST_MPI_PYTHON_SERIALIZE_HPP
0021 #define BOOST_MPI_PYTHON_SERIALIZE_HPP
0022
0023 #include <boost/mpi/python/config.hpp>
0024
0025 #include <boost/python/object.hpp>
0026 #include <boost/python/str.hpp>
0027 #include <boost/python/extract.hpp>
0028
0029 #include <map>
0030
0031 #include <boost/function/function3.hpp>
0032
0033 #include <boost/mpl/bool.hpp>
0034 #include <boost/mpl/if.hpp>
0035
0036 #include <boost/serialization/split_free.hpp>
0037 #include <boost/serialization/array.hpp>
0038 #include <boost/serialization/array_wrapper.hpp>
0039 #include <boost/smart_ptr/scoped_array.hpp>
0040
0041 #include <boost/assert.hpp>
0042
0043 #include <boost/type_traits/is_fundamental.hpp>
0044
0045 #define BOOST_MPI_PYTHON_FORWARD_ONLY
0046 #include <boost/mpi/python.hpp>
0047
0048 #include "bytesobject.h"
0049
0050
0051
0052
0053 #if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_IS_CONVERTIBLE)
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065 # define BOOST_PYTHON_SERIALIZATION_ARCHIVE(IArchiver, OArchiver) \
0066 namespace boost { namespace python { namespace api { \
0067 template<typename R, typename T> \
0068 struct enable_binary< IArchiver , R, T> {}; \
0069 \
0070 template<typename R, typename T> \
0071 struct enable_binary< OArchiver , R, T> {}; \
0072 } } }
0073 # else
0074 # define BOOST_PYTHON_SERIALIZATION_ARCHIVE(IArchiver, OArchiver)
0075 #endif
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090 #define BOOST_PYTHON_DIRECT_SERIALIZATION_ARCHIVE(IArchiver, OArchiver) \
0091 BOOST_PYTHON_SERIALIZATION_ARCHIVE(IArchiver, OArchiver) \
0092 namespace boost { namespace python { namespace detail { \
0093 template<> \
0094 BOOST_MPI_PYTHON_DECL direct_serialization_table< IArchiver , OArchiver >& \
0095 get_direct_serialization_table< IArchiver , OArchiver >(); \
0096 } \
0097 \
0098 template<> \
0099 struct has_direct_serialization< IArchiver , OArchiver> : mpl::true_ { }; \
0100 \
0101 template<> \
0102 struct output_archiver< IArchiver > { typedef OArchiver type; }; \
0103 \
0104 template<> \
0105 struct input_archiver< OArchiver > { typedef IArchiver type; }; \
0106 } }
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119 #define BOOST_PYTHON_DIRECT_SERIALIZATION_ARCHIVE_IMPL(IArchiver, OArchiver) \
0120 namespace boost { namespace python { namespace detail { \
0121 template \
0122 class BOOST_MPI_PYTHON_DECL direct_serialization_table< IArchiver , OArchiver >; \
0123 \
0124 template<> \
0125 BOOST_MPI_PYTHON_DECL \
0126 direct_serialization_table< IArchiver , OArchiver >& \
0127 get_direct_serialization_table< IArchiver , OArchiver >( ) \
0128 { \
0129 static direct_serialization_table< IArchiver, OArchiver > table; \
0130 return table; \
0131 } \
0132 } } }
0133
0134 namespace boost { namespace python {
0135
0136
0137
0138
0139
0140
0141 class BOOST_MPI_PYTHON_DECL pickle {
0142 struct data_t;
0143
0144 public:
0145 static object dumps(object obj, int protocol = -1);
0146 static object loads(object s);
0147
0148 private:
0149 static void initialize_data();
0150
0151 static data_t* data;
0152 };
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162 template<typename IArchiver, typename OArchiver>
0163 struct has_direct_serialization : mpl::false_ { };
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173 template<typename IArchiver> struct output_archiver { };
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184 template<typename OArchiver> struct input_archiver { };
0185
0186 namespace detail {
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198 template<typename IArchiver, typename OArchiver>
0199 class BOOST_MPI_PYTHON_DECL direct_serialization_table
0200 {
0201 public:
0202 typedef boost::function3<void, OArchiver&, const object&, const unsigned int>
0203 saver_t;
0204 typedef boost::function3<void, IArchiver&, object&, const unsigned int>
0205 loader_t;
0206
0207 typedef std::map<PyTypeObject*, std::pair<int, saver_t> > savers_t;
0208 typedef std::map<int, loader_t> loaders_t;
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225 saver_t saver(const object& obj, int& descriptor)
0226 {
0227 typename savers_t::iterator pos = savers.find(obj.ptr()->ob_type);
0228 if (pos != savers.end()) {
0229 descriptor = pos->second.first;
0230 return pos->second.second;
0231 }
0232 else {
0233 descriptor = 0;
0234 return saver_t();
0235 }
0236 }
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250 loader_t loader(int descriptor)
0251 {
0252 typename loaders_t::iterator pos = loaders.find(descriptor);
0253 if (pos != loaders.end())
0254 return pos->second;
0255 else
0256 return loader_t();
0257 }
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269 template<typename T>
0270 void register_type(const T& value = T(), PyTypeObject* type = 0)
0271 {
0272
0273
0274 if (!type) {
0275 object obj(value);
0276 type = obj.ptr()->ob_type;
0277 }
0278
0279 register_type(default_saver<T>(), default_loader<T>(type), value, type);
0280 }
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300 template<typename T>
0301 void register_type(const saver_t& saver, const loader_t& loader,
0302 const T& value = T(), PyTypeObject* type = 0)
0303 {
0304
0305
0306 if (!type) {
0307 object obj(value);
0308 type = obj.ptr()->ob_type;
0309 }
0310
0311 int descriptor = savers.size() + 1;
0312 if (savers.find(type) != savers.end())
0313 return;
0314
0315 savers[type] = std::make_pair(descriptor, saver);
0316 loaders[descriptor] = loader;
0317 }
0318
0319 protected:
0320 template<typename T>
0321 struct default_saver {
0322 void operator()(OArchiver& ar, const object& obj, const unsigned int) {
0323 T value = extract<T>(obj)();
0324 ar << value;
0325 }
0326 };
0327
0328 template<typename T>
0329 struct default_loader {
0330 default_loader(PyTypeObject* type) : type(type) { }
0331
0332 void operator()(IArchiver& ar, object& obj, const unsigned int) {
0333
0334 if (!is_fundamental<T>::value && obj && obj.ptr()->ob_type == type) {
0335 ar >> extract<T&>(obj)();
0336 } else {
0337 T value;
0338 ar >> value;
0339 obj = object(value);
0340 }
0341 }
0342
0343 private:
0344 PyTypeObject* type;
0345 };
0346
0347 savers_t savers;
0348 loaders_t loaders;
0349 };
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362 template<typename IArchiver, typename OArchiver>
0363 direct_serialization_table<IArchiver, OArchiver>&
0364 get_direct_serialization_table();
0365 }
0366
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386 template<typename IArchiver, typename OArchiver, typename T>
0387 void
0388 register_serialized(const T& value = T(), PyTypeObject* type = 0)
0389 {
0390 detail::direct_serialization_table<IArchiver, OArchiver>& table =
0391 detail::get_direct_serialization_table<IArchiver, OArchiver>();
0392 table.register_type(value, type);
0393 }
0394
0395 namespace detail {
0396
0397
0398 template<typename Archiver>
0399 void
0400 save_impl(Archiver& ar, const boost::python::object& obj,
0401 const unsigned int ,
0402 mpl::false_ )
0403 {
0404 boost::python::object bytes = boost::python::pickle::dumps(obj);
0405 int sz = PyBytes_Size(bytes.ptr());
0406 char *data = PyBytes_AsString(bytes.ptr());
0407 ar << sz << boost::serialization::make_array(data, sz);
0408 }
0409
0410
0411
0412 template<typename Archiver>
0413 void
0414 save_impl(Archiver& ar, const boost::python::object& obj,
0415 const unsigned int version,
0416 mpl::true_ )
0417 {
0418 typedef Archiver OArchiver;
0419 typedef typename input_archiver<OArchiver>::type IArchiver;
0420 typedef typename direct_serialization_table<IArchiver, OArchiver>::saver_t
0421 saver_t;
0422
0423 direct_serialization_table<IArchiver, OArchiver>& table =
0424 get_direct_serialization_table<IArchiver, OArchiver>();
0425
0426 int descriptor = 0;
0427 if (saver_t saver = table.saver(obj, descriptor)) {
0428 ar << descriptor;
0429 saver(ar, obj, version);
0430 } else {
0431
0432 ar << descriptor;
0433 detail::save_impl(ar, obj, version, mpl::false_());
0434 }
0435 }
0436
0437
0438 template<typename Archiver>
0439 void
0440 load_impl(Archiver& ar, boost::python::object& obj,
0441 const unsigned int ,
0442 mpl::false_ )
0443 {
0444 int len;
0445 ar >> len;
0446 boost::scoped_array<char> data(new char[len]);
0447 ar >> boost::serialization::make_array(data.get(), len);
0448 boost::python::object bytes(boost::python::handle<>(PyBytes_FromStringAndSize(data.get(), len)));
0449 obj = boost::python::pickle::loads(bytes);
0450 }
0451
0452
0453
0454 template<typename Archiver>
0455 void
0456 load_impl(Archiver& ar, boost::python::object& obj,
0457 const unsigned int version,
0458 mpl::true_ )
0459 {
0460 typedef Archiver IArchiver;
0461 typedef typename output_archiver<IArchiver>::type OArchiver;
0462 typedef typename direct_serialization_table<IArchiver, OArchiver>::loader_t
0463 loader_t;
0464
0465 direct_serialization_table<IArchiver, OArchiver>& table =
0466 get_direct_serialization_table<IArchiver, OArchiver>();
0467
0468 int descriptor;
0469 ar >> descriptor;
0470
0471 if (descriptor) {
0472 loader_t loader = table.loader(descriptor);
0473 BOOST_ASSERT(loader);
0474
0475 loader(ar, obj, version);
0476 } else {
0477
0478 detail::load_impl(ar, obj, version, mpl::false_());
0479 }
0480 }
0481
0482 }
0483
0484 template<typename Archiver>
0485 void
0486 save(Archiver& ar, const boost::python::object& obj,
0487 const unsigned int version)
0488 {
0489 typedef Archiver OArchiver;
0490 typedef typename input_archiver<OArchiver>::type IArchiver;
0491 detail::save_impl(ar, obj, version,
0492 has_direct_serialization<IArchiver, OArchiver>());
0493 }
0494
0495 template<typename Archiver>
0496 void
0497 load(Archiver& ar, boost::python::object& obj,
0498 const unsigned int version)
0499 {
0500 typedef Archiver IArchiver;
0501 typedef typename output_archiver<IArchiver>::type OArchiver;
0502 detail::load_impl(ar, obj, version,
0503 has_direct_serialization<IArchiver, OArchiver>());
0504 }
0505
0506 template<typename Archive>
0507 inline void
0508 serialize(Archive& ar, boost::python::object& obj, const unsigned int version)
0509 {
0510 boost::serialization::split_free(ar, obj, version);
0511 }
0512
0513 } }
0514
0515
0516
0517
0518 namespace boost { namespace mpi {
0519 class packed_iarchive;
0520 class packed_oarchive;
0521 } }
0522
0523 BOOST_PYTHON_DIRECT_SERIALIZATION_ARCHIVE(
0524 ::boost::mpi::packed_iarchive,
0525 ::boost::mpi::packed_oarchive)
0526
0527 namespace boost { namespace mpi { namespace python {
0528
0529 template<typename T>
0530 void
0531 register_serialized(const T& value, PyTypeObject* type)
0532 {
0533 using boost::python::register_serialized;
0534 register_serialized<packed_iarchive, packed_oarchive>(value, type);
0535 }
0536
0537 } } }
0538
0539 #endif