Hi Diederick, You may take a look at the following link for the discussion of generic Singleton pattern with testing code, so far the best one I have ever read about Singleton pattern: http://www.devarticles.com/c/a/Cplusplus/C-plus-plus-In-Theory-The-Singleton... I hope this helps, Robert On Sat, Jul 25, 2009 at 10:44 PM, Diederick C. Niehorster <dcnieho@gmail.com
wrote:
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 mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users