2009-04-16 9 views
1

Dans mon programme, j'ai un objet le fichier global cpp, qui prend un entier comme argument.C++ Random Seed, objets globaux et SDL_Threads

//In global header 
extern Object example; 

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

Je veux un nombre aléatoire à générer à l'argument de l'objet, mais la graine n'atteint pas la variable globale, comme la graine créée dans un autre fichier cpp, qui est appelé plus tard dans la principale.

Mon problème principal est que la graine aléatoire n'atteint pas l'argument de l'objet dans global.cpp, mais je l'ai aussi mis là pour une raison spécifique, ce qui implique des threads.

Ma question principale est: Une graine aléatoire peut-elle atteindre une variable globale? si oui, s'il vous plaît me dire comment

(même si oui, la question suivante est hors de propos)

Mais si ce n'est pas possible, cette question qui concerne les discussions et où créer l'objet. La classe d'objet appelle une fonction en fil d'exécution et appelle une autre fonction sur un autre thread, comme les suivantes:

// thread A

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

    return 0; 
} 

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

    return 0; 
} 

Je veux ce genre de fonctionnalité entre les 2 fils, mais existe-t-il un moyen d'y parvenir sans créer l'objet dans les globales?

Répondre

0

Il semble que vous utilisiez une approche qui se décline selon l'ordre d'initialisation de la statique (globals). Vous ne pouvez pas dépendre de cet ordre dans les unités de compilation (c'est-à-dire dans des fichiers différents). Les statistiques de la même unité de compilation sont initialisées dans l'ordre dans lequel elles sont déclarées.

Pour les solutions, vous pourriez envisager ceci:

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

1

La meilleure façon de le faire serait d'utiliser le modèle singleton (notez que cet exemple est pas 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()); 

Pour mettre en œuvre la sécurité du filetage, utilisez un double verrouillage ou un autre mécanisme de verrouillage. Une autre option serait de regarder Boost.call_once pour initialiser les données pour vous.

0

Vous faites face à static initialization problem. La solution la plus simple consiste à implémenter un Singleton afin de pouvoir contrôler le processus d'initialisation. Comme vous utilisez du code multithread, le singleton devra être thread-safe (considérez le modèle double check locking) pour la création, et probablement un mutex et une condition pour éviter les conditions de course. Consultez la documentation de votre bibliothèque de threads pour la documentation sur cette partie. Le pseudo-code général serait:

// 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(); 
} 

Votre bibliothèque de threads a probablement de meilleures constructions (RAII pour l'acquisition de mutex et la libération()), mais l'idée est que vous avez un seul point où les deux threads attendent que l'autre compléter leurs tâches afin qu'il n'y ait pas de condition de thread.