2010-09-24 7 views
0
boost::condition_variable cond; 
boost::mutex mut; 

void Database::run() 
{ 
    boost::unique_lock<boost::mutex> lock(mut); 

    while(true) 
    { 
     while(queries_queue.empty()) 
      cond.wait(lock); 

     mysqlpp::Query* q = queries_queue.front(); // <<< CRASHES HERE <<< 
     q->execute(); 
     queries_queue.pop_front(); 
    } 
} 

void Database::Execute(mysqlpp::Query* q) 
{ 
    { 
     boost::lock_guard<boost::mutex> lock(mut); 
     queries_queue.push_back(q); 
    } 
    cond.notify_one(); 
} 

L'exécution est exécutée par boost :: thread. L'exécution est appelée par l'unité d'exécution du programme principal pour mettre en file d'attente une opération. Cependant, il se bloque après le réveil de l'attente conditionnelle.condition de suralimentation. Qu'est-ce que je fais mal?

Qu'est-ce que je fais mal?

+0

btw, vous devriez donner à vos variables de condition un nom plus descriptif – sellibitze

+0

btw2, est-il intentionnel, que le mutex soit toujours verrouillé pendant que la fonction q-> execute() est exécutée? – sellibitze

+0

Je ne vois rien de mal à cela. L'erreur pourrait être ailleurs. – sellibitze

Répondre

-1

essayer

while(true) 
{ 
    boost::unique_lock<boost::mutex> lock(mut); 
    while(queries_queue.empty()) 
     cond.wait(lock); 
+0

Cela n'a aucun sens de re-verrouiller le 'mutex'. C'est ce que 'condition :: wait' pour signifier. –

+0

@Vlad: Je pense que aaa signifie déplacer le 'boost :: unique_lock lock (mut);' de la portée de fonction à 'while (true)' dans 'Database :: run' sans en ajouter un autre. –

+0

@Eugen: Exactement, et cela introduira un verrouillage/déverrouillage à chaque interation de boucle while. Ce qui est très nocif. –

2

Votre code de filetage semble bon. La seule chose qui sent mélange lock_guard et unique_lock mais ce n'est pas une grosse affaire. Cependant, je suis sûr à 99% que votre code ne plante pas là où vous l'avez indiqué, mais sur la ligne suivante - q->execute();. Il semble que l'appelant de la méthode Database::Execute() passe un pointeur vers un objet de requête alloué sur une pile ou, s'il est alloué dynamiquement, il le supprime juste après la fin de la fonction. Plus tard, cependant, votre thread réessaye de pointer vers cet objet supprimé (libéré ou détruit) et essaie de l'exécuter. Une autre possibilité est que le pointeur NULL est passé au Database::Execute() qui conduit au même résultat.

+2

'lock_guard' est bien, s'il n'a pas besoin de passer l'objet lock à une variable de condition. –

+0

Essayé commentant q-> exécuter et supprimer q out. L'accident a persisté. Mais quand j'ai supprimé les deux références à queries_queue, cela a fonctionné. – Vladimir

+0

@Vladimir: Y at-il autre chose qui accède à 'queries_queue' sans verrouiller? De plus, je ne vois aucun 'delete q;' dans votre exemple. Cela aiderait beaucoup si vous pouviez fournir un exemple de code de travail minimal qui se bloque. Sinon, c'est toujours deviner. Mais le problème n'est certainement pas dans le code de threading que vous avez fourni jusqu'à présent. –

Questions connexes