web-dev-qa-db-fra.com

Utilisation d'un thread boost et d'une fonction de classe non statique

J'ai donc effectué des recherches et découvert que vous pouvez créer un objet boost :: thread et le faire démarrer par une fonction de classe non statique en utilisant "this" et boost :: bind, etc. Cela n'a vraiment aucun sens. Pour moi et tous les exemples que je pouvais trouver, l'objet boost :: thread avait été lancé dans la même classe que la fonction avec laquelle il était démarré, afin que celui-ci puisse être utilisé. Cependant, je lance le fil dans une classe différente, je crains donc d’utiliser «ceci». Je dirai que «ceci» provient de la classe dont je crée le fil, plutôt que celui dans lequel la fonction se trouve J'ai probablement tort, j'ai besoin d'en savoir plus sur ce "ce" gars). Voici un exemple de ma source avec laquelle je rencontre le problème.

ANNGUI.h

 class ANNGUI 
 {
 private: 
 boost :: thread * GUIThread; 
 Main * GUIMain; 
 Public: 
 // Crée l'intégralité de l'interface graphique et toutes les sous-parties .
 int CreateGUI (); 
} 

ANNGUI.cpp

 int ANNGUI :: CreateGUI () 
 {
 GUIMain = new Main (); 
 GUIThread = new boost :: thread (GUIMain-> MainThreadFunc); 
}; 

Ce n'est pas toute la source, mais je pense que mon problème est ici quelque part, je sais que je dois faire face au "ceci" d'une manière ou d'une autre, mais je ne sais pas comment. Je pourrais utiliser une fonction statique, mais je ne voulais pas non plus vraiment rendre mes variables statiques .. .. Merci.

En outre, existe-t-il une très bonne ressource pour utiliser des bibliothèques boost? La documentation de leur site Web semble bonne, mais au-dessus de ma tête.

43
contrapsych

Le mot clé this est utilisé avec boost::bind lorsque l'objet fonction que vous créez est lié à un membre object, fonction . Les fonctions membres ne peuvent pas exister en dehors des instances. Ainsi, lors de la création d'un objet foncteur hors d'une fonction membre avec boost::bind, vous avez besoin d'un pointeur sur une instance. C'est exactement ce que le mot clé this est en réalité. Si vous utilisez le mot clé this au sein d'une fonction membre d'une classe, vous obtenez un pointeur sur l'instance actuelle de cette classe.

Si vous appelez bind depuis extérieur une fonction de membre de classe, vous pourriez dire quelque chose comme:

int main()
{
  Foo f;
  boost::thread* thr = new boost::thread(boost::bind(&Foo::some_function, &f));
}

Ici, nous utilisons Foo :: some_function comme fonction de thread. Mais nous ne pouvons pas utiliser this car nous appelons bind à partir de main. Mais la même chose pourrait être obtenue en utilisant this si nous appelions bind depuis une fonction membre de Foo, comme suit:

void Foo::func1()
{
  boost::thread* thr = new boost::thread(boost::bind(&Foo::some_function, this));
}

Si une fonction membre est statique ou est simplement une fonction régulière (non membre), vous n'avez pas du tout besoin d'un pointeur d'instance. Vous feriez juste:

boost::thread* thr = new boost::thread(some_regular_function);
81
Charles Salvia

Comme d'autres l'ont mentionné, lorsque vous souhaitez appeler une méthode d'objet dans un nouveau thread, vous devez fournir l'adresse de cet objet. Mais vous n'avez pas besoin d'appeler boost::bind, vous pouvez utiliser le constructeur surchargé boost::thread comme ceci:

GUIThread = new boost::thread(&Main::MainThreadFunc, GUIMain);

Si la méthode est dans la même classe, utilisez this pour obtenir l'adresse de l'instance actuelle, par exemple:

t = new boost::thread(&myclass::compute, this);

Si la méthode a des paramètres, vous pouvez les spécifier après le deuxième argument, par exemple:

t = new boost::thread(&myclass::compute, this, p1, p2);
40
maxschlepzig

boost :: bind est votre ami (il peut parfois avoir un moyen rude de le montrer)!

utiliser GUIThread = new boost::thread(boost::bind(&Main::MainThreadFunc, GUIMain));

puis faites de votre MainThreadFunc un membre régulier. Cela signifie que vous pouvez utiliser les variables d'instance directement comme vous le feriez normalement.

Quelque chose comme ça:

class GUIMain {
public:
  GUIMain() : m_Member(42) {}

  void MainThreadFunc() {
    // use all members as you would normally do
    std::cout << m_Member << std::endl;
  }

private:
  int m_Member;
};
3
villintehaspam

Dans de tels cas, il est utile de considérer les fonctions membres non statiques comme des fonctions libres prenant le premier paramètre this, par exemple dans votre cas void MainThreadFunc(Main* this)

boost::thread accepte un foncteur nullary, vous devez donc lui passer un foncteur nullary qui contient une référence à l'instance GUIMain et appelle GUIMain->MainThreadFunc qui, comme je l'ai expliqué plus haut, ressemblerait à MainThreadFunc(GUIMain)

Boost (et maintenant aussi C++ avec TR1) fournit des aides pour créer de tels foncteurs, à savoir boost::bind (ou alternativement boost::lambda::bind). L’expression boost::bind(f, arg1, arg2, ...) signifie "renvoie un foncteur nullary qui appelle f(arg1, arg2, ...)".

Cela dit, vous pouvez utiliser l'expression suivante pour créer le fil de discussion:

GUIThread = new boost::thread(boost::bind(&Main::MainThreadFunc, GUIMain))
3
Giuseppe Ottaviano

Si votre objet est un foncteur, c’est-à-dire qu’il a une operator(), vous pouvez en transmettre une instance à boost::thread. La operator() n'a pas besoin d'être statique. Par exemple:

#include <boost/thread.hpp>

struct th {
    void operator()();
};

void th::operator()()
{
    for (;;) {
        // stuff
    }
}

int main()
{
    th t;
    boost::thread my_thread( t ); // takes a copy of t !
    my_thread.join(); // blocks
    return 0;
}
1
Bulletmagnet