views:

421

answers:

3

In my program, I have an object the global cpp file, that takes an integer as an argument.

//In global header
extern Object example;

//In global cpp file
Object example( (rand() % 6) );

I want a random number to be generated to the object's argument, but the seed does not reach the global variable, as the seed created in another cpp file, which is called later in the main.

My main problem is the random seed does not reach argument of the object in global.cpp, but I also put there for a specific reason, which involves threads.

My main question is: Can a random seed reach a global variable? if yes, please tell me how

(ALSO if yes, the next question is irrelevant)

But if it's not possible, this question regards to threads and the where to create the object. The object class calls a function in run thread, and calls a different function on another thread, such as the following:

//Thread A

int thread(void *data)
{
   example.showimage();

   return 0;
}

//ThreadB
int thread(void *data(
{
   example.moveimage();

   return 0;
}

I want this kind of functionality between the 2 threads, but is there a way to achieve this without creating the object in globals?

A: 

It sounds like you're using an approach that relys on order of initialization of statics (globals). You cannot depend on that order across compilation units (i.e. in different files). Statics in the same compilation unit are initialized in the order they are declared.

For solutions, you might consider this:

How do I prevent the "static initialization order fiasco"?

Don Neufeld
+1  A: 

The best way to do this would be to use the singleton pattern (note that this example is NOT threadsafe):

//in a header
class RandomSeed
{
public:
    static RandomSeed& instance()
    {
        static RandomSeed the_instance;
        return the_instance;
    }
    int value() const {return value_;}
private:
    RandomSeed() {/*initialization code*/}
    RandomSeed(const RandomSeed& rs); // disallowed
    RandomSeed& operator=(const RandomSeed& rs); // disallowed
    int value_;
};

// in your file
#include "random_seed.h"
srand(RandomSeed::instance().value());

To implement thread safety, either use a double-lock or some other locking mechanism. Another option would be to look at Boost.call_once to initialize the data for you.

rlbond
A: 

You are facing a static initialization problem. The easiest way out is implemeting a Singleton so that you can control the initialization process. As you are using multithreaded code, the Singleton will have to be thread-safe (consider the double check locking) pattern for creation, and probably a mutex and a condition to avoid race conditions. Check your threading library documentation for documentation on this part. The general pseudo code would be:

// image_control would be 'example' in your two last snippets
// painter
image image_control::obtain_picture()
{
   mutex.acquire();
   while ( ! image_already_created ) 
      image_creation_condition.wait(); // wait for image creation
   image res = the_image;
   image_already_created = false; // already consumed
   image_consumption_condition.signal(); // wake up producer is waiting
   mutex.release();
   return res;
}
// image creator
void image_control::create_picture( image new_image )
{
   mutex.acquire();
   while ( image_already_created ) 
      image_consumption_condition.wait(); // wait for image to be consumed
   the_image = new_image;
   image_already_created = true;
   image_creation_condition.signal(); // wake up consumer if it is waiting
   mutex.release();
}

Your threading library probably has better constructs (RAII for mutex acquisition and release()) but the idea is that you have a single point where the two threads wait for the other to complete their tasks so that there is no thread condition.

David Rodríguez - dribeas