Boost logo

Boost Users :

Subject: Re: [Boost-users] [random] Singleton engine
From: Robert Ramey (ramey_at_[hidden])
Date: 2009-07-26 01:22:50


Maybe you want to try the one in the serialization library.

Robert Ramey

Diederick C. Niehorster 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 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