The solution to my problem is a combination of boost::serialization and
boost::shared_ptr.
Rather than holding refs to the contained shared objects, if the objects are
share_ptr, then serialization will do the correct thing.
For example, I have
struct boost_uniform_int_wrap {
boost::shared_ptr<rng_t> rng_obj;
boost::uniform_int<> gen;
boost_uniform_int_wrap (boost::shared_ptr<rng_t> _rng_obj, int min, int max) :
rng_obj (_rng_obj),
gen (min, max) {}
...
struct uniform_int_pickle_suite : bp::pickle_suite {
static bp::tuple getinitargs (boost_uniform_int_wrap const& gen) {
return bp::make_tuple (gen.rng_obj, gen.gen.min(), gen.gen.max());
}
};
Also, I have modified mersenne_twister to make it serializable (very simple to
add).
Then to make mersenne_twister pickleable:
typedef boost::mt19937 rng_t;
struct mt_pickle_suite : bp::pickle_suite {
static bp::object getstate (const rng_t& rng) {
std::ostringstream os;
boost::archive::binary_oarchive oa(os);
oa << rng;
return bp::str (os.str());
}
static void
setstate(rng_t& rng, bp::object entries) {
bp::str s = bp::extract<bp::str> (entries)();
std::string st = bp::extract<std::string> (s)();
std::istringstream is (st);
boost::archive::binary_iarchive ia (is);
ia >> rng;
}
};
Now:
from boost_rand import rng, normal
from sys import getrefcount
rng1 = rng()
print getrefcount(rng1)
n1 = normal (rng1, 1, 0)
print getrefcount(rng1)
n2 = normal (rng1, 1, 0)
print getrefcount(rng1)
from cPickle import dumps, loads
rng2, n3, n4 = loads (dumps ((rng1, n1, n2), -1))
In [10]: ## working on region in file /usr/tmp/python-18983NT.py...
2
3
4
In [11]: rng2
Out[11]: <boost_rand.rng at 0x307c838>
In [12]: n3.rng
Out[12]: <boost_rand.rng at 0x307c838>
In [13]: n4.rng
Out[13]: <boost_rand.rng at 0x307c838>
_______________________________________________
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig