Design Difficulties

Started by
1 comment, last by Antheus 12 years, 6 months ago
Hiya,

I have a number of worker threads, all taking jobs from a queue. The jobs use several objects which must access a structure from a non thread-safe third-party library - so each thread ideally needs its own structure. Could anyone suggest a way of giving the objects access to the shared structure?

The structure is actually the state of a RNG, so I'd rather not initialise a new one in each class where it's needed as its expensive. I'm tempted to use a singleton with Boost thread-local storage, something like this:


class RandomGenerator
{
public:

static RandomGenerator* instance()
{
boost::thread_specific_ptr<RandomGenerator> threadInstance;
if(threadInstance.get() == 0)
threadInstance.reset(new RandomGenerator());

return threadInstance;
}

/* Return the actual structure. */
gmp_randstate_t& getState() const
{
return m_state;
}

private:

RandomGenerator() { /* etc. */ }

mutable gmp_randstate_t m_state;
};


It seems messy and I'd rather not use a singleton if possible.

Any suggestions are appreciated!

Thanks.
Advertisement
A simple static (or module scoped instance) with thread-local storage is pretty common. Though honestly, I can't think of any RNG implementation that is particularly heavyweight...

Hiya,

I have a number of worker threads, all taking jobs from a queue. The jobs use several objects which must access a structure from a non thread-safe third-party library - so each thread ideally needs its own structure.


Thread-safety is a vaguely defined and often misused term.

Having one copy per thread does not make it thread safe. At least not in absence of having the source and making sure that per-thread isolation does indeed provide sufficient isolation.

Consider a simple example of a logger. Each thread could have its own instance, yet they would all be writing to same file.

Could anyone suggest a way of giving the objects access to the shared structure?[/quote]

A problem like this is solved via a queue. All threads serialize requests into a single queue, which is then handled by one single thread.

I'm tempted to use a singleton with Boost thread-local storage, something like this:[/quote]
Singletons and concurrency don't mix. If implemented properly, they block, so that only a single thread may access them at same time. Otherwise, they are no longer a singleton, since multiple copies exist.

All the previously mentioned issues exist. If source isn't available, there is no guarantee that multiple copies will behave properly. A true RNG with external data source would still be polling same resource, despite multiple copies existing inside an application.

That said, for PRNG, just about every useful implementation provides ability to specify own seed. If it doesn't, ditch it and use a library that does. All good PRNGs are available in suitable form in many forms and different licenses.

And even if it takes 30 seconds to initialize, it makes no difference. If done on single thread, it will take 30 seconds, if done on n threads it will still take 30 seconds, just each thread initializing on its own. For user it doesn't matter.

This topic is closed to new replies.

Advertisement