|
Boost Users : |
Subject: [Boost-users] [random] Singleton engine
From: Diederick C. Niehorster (dcnieho_at_[hidden])
Date: 2009-07-25 22:44:50
Hi All,
I have been writing a wrapper around the variate_generator as I always
want to use the same number generator, but do want to use different
distributions. As I want to use only one instance of the engine
instance for all instanced of my random number generator class, I used
a singleton pattern. as is my first time using it, I decided to test
it generously, to try and see if the same instance of the enigine is
used.
So not only did i check if the engine pointer for different instances
of my random class is the same, but i also checked if the destructor
for the engine (does not) get called (i've added a constructor to the
boost header file temporarily) and whether the random numbers
generated are indeed not the same.
It seems my code does not work, the destructor gets called weirdly
often, e.g., 4 times every time i initialize my random class. Also,
the numbers generated by the two generators are the same, indicating
the engine is reinitialized for every instance of my random class.
Yet, the pointer to the engine is the same (note that it is also the
same if i dont call the destructor in between).
I am using MSVC 2008 on windows XP 32 bit.
What am I doing wrong? As I am learning, any other feedback is also
very welcome.
Best,
Diederick
---- output of run of code below: check 0 00000000 ctor 1 destructor destructor destructor destructor after ctor 1 003462E0 random: 8148 dtor 1 destructor ctor 2 destructor destructor destructor destructor after ctor 2 003462E0 random: 8148 destructor destructor ---- code // includes #include <boost/random.hpp> #include <time.h> #include <iostream> using namespace std; // declaration template<class Dist> class CRandom { public: /** use for Dist: CRandomI Ci(min,max); uses uniform_int<int> - integral types CRandomR Cr(min,max); uses uniform_real<double> - floating point types for other ditributions or types, use: CRandom<distribution<optional type>> Cr(0--3 params, depending on distribution); for distributions and params, see: http://www.boost.org/doc/libs/1_39_0/libs/random/random-distributions.html */ // forwarding constructors explicit CRandom() : Gen(*EngineSingleton::Eng(), Dist()) { } template<class P> explicit CRandom(const P & p1) : Gen(*EngineSingleton::Eng(), Dist(p1)) { } template<class P> explicit CRandom(const P & p1, const P & p2) : Gen(*EngineSingleton::Eng(), Dist(p1, p2)) { } template<class P> explicit CRandom(const P & p1, const P & p2, const P & p3) : Gen(*EngineSingleton::Eng(), Dist(p1, p2, p3)) { } ~CRandom(void) {}; typedef typename Dist::result_type result_type; result_type operator()() { return Gen(); } template<class T> result_type operator()(T value) { return Gen(value); } private: boost::variate_generator<boost::mt19937,Dist> Gen; }; // end declaration // shorthand typedefs typedef CRandom<boost::uniform_int<int>> CRandomI; // even int is default type , specify it in case it ever changes typedef CRandom<boost::uniform_real<double>> CRandomR; // even double is default type, specify it in case it ever changes /** engine wrapper class following singleton pattern, so every instantiation of CRandom uses the same engine based on: http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf */ // declaration class EngineSingleton { public: static boost::mt19937* Eng(); static boost::mt19937* GetEngPoint() {return pEng;}; // for test only protected: // disallow (copy) construction and assignment operator EngineSingleton(); EngineSingleton(const EngineSingleton&); EngineSingleton& operator=(const EngineSingleton&); private: static boost::mt19937* pEng; }; // end declaration // implementation boost::mt19937* EngineSingleton::pEng = NULL; boost::mt19937* EngineSingleton::Eng() { if (pEng == NULL) { pEng = new boost::mt19937(/*unsigned int(time(NULL))*/); // initialize with same seed always, for test only } return pEng; } // end implementation //main int main(int argc, char* argv[]) { cout << "check 0" << endl; cout << EngineSingleton::GetEngPoint() << endl; cout << "ctor 1" << endl; CRandomI Cr(1,10000); cout << "after ctor 1" << endl; cout << EngineSingleton::GetEngPoint() << endl; int test = Cr(); cout << "random: " << test << endl; cout << "dtor 1" << endl; Cr.~CRandom(); cout << "ctor 2" << endl; CRandomI Cr2(1,10000); cout << "after ctor 2" << endl; cout << EngineSingleton::GetEngPoint() << endl; int test2 = Cr2(); cout << "random: " << test2 << endl; // exit return 1; }
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net