Boost logo

Boost Users :

Subject: Re: [Boost-users] [random] Singleton engine
From: Diederick C. Niehorster (dcnieho_at_[hidden])
Date: 2009-07-28 20:14:20


Hi Kevin,

Thank you for your suggestions, I have learned from your code but
don't think it is optimally suited for my needs.

Hi Robert,
Thank you for the tip, however, it seems not possible to seed my
engine during construction (that is call the constructor with an
parameter) with your singleton class.

Hi Boost lzw,
Thats a great article, I'll study it and probably use that code as it
seems flexible and suitable for my needs (after a quick glance).

In general, wouldn't it be a good idea to have a singleton library
inside boost? To my understanding they are used quite often, so better
provide the world with a (few) good implementation(s suited for
different needs). What do you think?

Best,
Diederick

On Sun, Jul 26, 2009 at 11:15 AM, Boost lzw<boostlzw_at_[hidden]> wrote:
> 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-Pattern-Part-2/2/
>
> I hope this helps,
> Robert
>
>
> On Sat, Jul 25, 2009 at 10:44 PM, Diederick C. Niehorster
> <dcnieho_at_[hidden]> 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_at_[hidden]
>> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>
>
> _______________________________________________
> Boost-users mailing list
> Boost-users_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>


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