'Is this a thread-safe RNG method?

Is it safe to call A::generateID() from multiple threads?

class A
{
public:
    std::string generateID()
    {
        unsigned long rndNumber = dist(gen);
    
        std::string result;
        result.resize(5);
    
        result[0] = LETTERS[(rndNumber >> (6*0)) & 0x3f];
        result[1] = LETTERS[(rndNumber >> (6*1)) & 0x3f];
        result[2] = LETTERS[(rndNumber >> (6*2)) & 0x3f];
        result[3] = LETTERS[(rndNumber >> (6*3)) & 0x3f];
        result[4] = LETTERS[(rndNumber >> (6*4)) & 0x3f];
    
        return result;
    }

private:
    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
    std::mt19937_64 gen = std::mt19937_64(seed); //Has the best performance compared to other RNG engines
    std::uniform_int_distribution<unsigned long> dist = std::uniform_int_distribution<unsigned long>(0, std::numeric_limits<unsigned long>::max());

    const std::string LETTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789&$";
};

Of course, the easiest way would be just putting everything in generateID() but I want to do as much work as possible in the object instatiation to make the function call as fast as possible and it must be thread-safe. The problem is, dist(gen) seems to change the internal state of the RNG engine but I can't find any information about the race conditions of std::uniform_int_distribution::operator().



Solution 1:[1]

Absolutely not, uniform_int_distribution is not thread safe.

And it's actually much worse, because you're using one uniformly-distributed random value and generate 5 random values from it that are absolutely not uniformly-distributed. If you want 5 random values, request 5 values from your generator. You're not gaining anything with your anti-pattern.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Blindy