Start thread met lidfunctie

Ik probeer een std::threadte construeren met een lidfunctie die geen argumenten aanneemt en voidretourneert. Ik kan geen enkele syntaxis vinden die werkt – de compiler klaagt hoe dan ook. Wat is de juiste manier om spawn()te implementeren zodat het een std::threadretourneert die test()uitvoert?

#include <thread>
class blub {
  void test() {
  }
public:
  std::thread spawn() {
    return { test };
  }
};

Antwoord 1, autoriteit 100%

#include <thread>
#include <iostream>
class bar {
public:
  void foo() {
    std::cout << "hello from member function" << std::endl;
  }
};
int main()
{
  std::thread t(&bar::foo, bar());
  t.join();
}

BEWERKEN:
Je bewerking verantwoorden, je moet het als volgt doen:

 std::thread spawn() {
    return std::thread(&blub::test, this);
  }

UPDATE:ik wil nog enkele punten toelichten, sommige zijn ook besproken in de opmerkingen.

De hierboven beschreven syntaxis is gedefinieerd in termen van de INVOKE-definitie (§20.8.2.1):

Definieer INVOKE (f, t1, t2, …, tN) als volgt:

  • (t1.*f)(t2, …, tN) wanneer f een pointer is naar een lidfunctie van een klasse T en t1 een object van het type T is of een verwijzing naar een object van
    type T of een verwijzing naar een object van een type afgeleid van T;
  • ((*t1).*f)(t2, …, tN) wanneer f een pointer is naar een lidfunctie van een klasse T en t1 niet een van de typen is die in het voorgaande zijn beschreven
    artikel;
  • t1.*f wanneer N == 1 en f is een verwijzing naar lidgegevens van een klasse T en t 1 is een object van het type T of a
    verwijzing naar een object van het type T of een verwijzing naar een object van a
    type afgeleid van T;
  • (*t1).*f wanneer N == 1 en f een verwijzing is naar lidgegevens van een klasse T en t 1 niet een van de typen is die in het vorige item zijn beschreven;
  • f(t1, t2, …, tN) in alle andere gevallen.

Een ander algemeen feit waar ik op wil wijzen, is dat de threadconstructor standaard alle argumenten die eraan worden doorgegeven, kopieert. De reden hiervoor is dat de argumenten mogelijk de aanroepende thread moeten overleven, en het kopiëren van de argumenten garandeert dat. Als je een referentie echt wilt doorgeven, kun je in plaats daarvan een std::reference_wrappergebruiken die is gemaakt door std::ref.

std::thread (foo, std::ref(arg1));

Door dit te doen, belooft u dat u ervoor zult zorgen dat de argumenten zullen blijven bestaan ​​wanneer de thread erop actief is.


Houd er rekening mee dat alle bovengenoemde dingen ook kunnen worden toegepast op std::asyncen std::bind.


Antwoord 2, autoriteit 27%

Omdat je C++11 gebruikt, is lambda-expression een mooie en schone oplossing.

class blub {
    void test() {}
  public:
    std::thread spawn() {
      return std::thread( [this] { this->test(); } );
    }
};

aangezien this->kan worden weggelaten, kan het worden ingekort tot:

std::thread( [this] { test(); } )

of gewoon(verouderd)

std::thread( [=] { test(); } )


Antwoord 3, autoriteit 8%

Hier is een compleet voorbeeld

#include <thread>
#include <iostream>
class Wrapper {
   public:
      void member1() {
          std::cout << "i am member1" << std::endl;
      }
      void member2(const char *arg1, unsigned arg2) {
          std::cout << "i am member2 and my first arg is (" << arg1 << ") and second arg is (" << arg2 << ")" << std::endl;
      }
      std::thread member1Thread() {
          return std::thread([=] { member1(); });
      }
      std::thread member2Thread(const char *arg1, unsigned arg2) {
          return std::thread([=] { member2(arg1, arg2); });
      }
};
int main(int argc, char **argv) {
   Wrapper *w = new Wrapper();
   std::thread tw1 = w->member1Thread();
   std::thread tw2 = w->member2Thread("hello", 100);
   tw1.join();
   tw2.join();
   return 0;
}

Compileren met g++ levert het volgende resultaat op

g++ -Wall -std=c++11 hello.cc -o hello -pthread
i am member1
i am member2 and my first arg is (hello) and second arg is (100)

Antwoord 4, autoriteit 6%

@hop5 en @RnMss stelden voor om C++11 lambdas te gebruiken, maar als je met pointers werkt, kun je ze direct gebruiken:

#include <thread>
#include <iostream>
class CFoo {
  public:
    int m_i = 0;
    void bar() {
      ++m_i;
    }
};
int main() {
  CFoo foo;
  std::thread t1(&CFoo::bar, &foo);
  t1.join();
  std::thread t2(&CFoo::bar, &foo);
  t2.join();
  std::cout << foo.m_i << std::endl;
  return 0;
}

uitgangen

2

Herschreven voorbeeld van dit antwoordzou dan zijn:

#include <thread>
#include <iostream>
class Wrapper {
  public:
      void member1() {
          std::cout << "i am member1" << std::endl;
      }
      void member2(const char *arg1, unsigned arg2) {
          std::cout << "i am member2 and my first arg is (" << arg1 << ") and second arg is (" << arg2 << ")" << std::endl;
      }
      std::thread member1Thread() {
          return std::thread(&Wrapper::member1, this);
      }
      std::thread member2Thread(const char *arg1, unsigned arg2) {
          return std::thread(&Wrapper::member2, this, arg1, arg2);
      }
};
int main() {
  Wrapper *w = new Wrapper();
  std::thread tw1 = w->member1Thread();
  tw1.join();
  std::thread tw2 = w->member2Thread("hello", 100);
  tw2.join();
  return 0;
}

Antwoord 5

Sommige gebruikers hebben hun antwoord al gegeven en heel goed uitgelegd.

Ik zou nog een paar dingen willen toevoegen die te maken hebben met threads.

  1. Hoe te werken met functor en draad.
    Raadpleeg het onderstaande voorbeeld.

  2. De thread maakt zijn eigen kopie van het object terwijl het het object passeert.

    #include<thread>
    #include<Windows.h>
    #include<iostream>
    using namespace std;
    class CB
    {
    public:
        CB()
        {
            cout << "this=" << this << endl;
        }
        void operator()();
    };
    void CB::operator()()
    {
        cout << "this=" << this << endl;
        for (int i = 0; i < 5; i++)
        {
            cout << "CB()=" << i << endl;
            Sleep(1000);
        }
    }
    void main()
    {
        CB obj;     // please note the address of obj.
        thread t(obj); // here obj will be passed by value 
                       //i.e. thread will make it own local copy of it.
                        // we can confirm it by matching the address of
                        //object printed in the constructor
                        // and address of the obj printed in the function
        t.join();
    }
    

Een andere manier om hetzelfde te bereiken is als volgt:

void main()
{
    thread t((CB()));
    t.join();
}

Maar als u het object als referentie wilt doorgeven, gebruik dan de onderstaande syntaxis:

void main()
{
    CB obj;
    //thread t(obj);
    thread t(std::ref(obj));
    t.join();
}

Other episodes