c++ wątki pod linuxem

0

Witam
Moj problem polega na tym ze nie moge sobie poradzic z wątkiem który ma wykonać metode bez argumentów. O to mój kod:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h> //funkcja ntoa
#include <iostream>
#include <list> // listy
#include <pthread.h> //watki
void error(const char *msg)
{
        perror(msg);
        exit(1);
 }
 using namespace std;
class sesja
{
        public:
        void *run()
        {
                sockfd = socket(AF_INET, SOCK_STREAM, 0);
                if (sockfd < 0)
                        error("ERROR Nie moge otworzyæ gniazda");
                bzero((char *) &serv_addr, sizeof(serv_addr));
                portno = atoi("2000");
                serv_addr.sin_family = AF_INET;
                serv_addr.sin_addr.s_addr = INADDR_ANY;
                serv_addr.sin_port = htons(portno);
                if (bind(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
                {
                        error("ERROR on binding");
                }
                listen(sockfd,5);
                clilen = sizeof(cli_addr);
                while(true)
                {
                        newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr,&clilen);
                        if (newsockfd < 0)
                                error("ERROR on accept");
                        cout << "Polaczenie z hostem  " << inet_ntoa(cli_addr.sin_addr) << endl;
                        bzero(buffer,256);
                }
                close(sockfd);
                return NULL;
        }
        void *listens()
        {
                while(true)
                {
                         memset (buffer, 0, 256 );
                        n = read(newsockfd,buffer,255);
                        if (n < 0)
                        {
                                error("ERROR odczyt z gniazda");
                        }
                        if (!strncmp(buffer, "/exit", 5))
                        {
                                n = write(newsockfd,"Wylaczam server",15);
                                 break;
                        }
                }
                close(newsockfd);
                return NULL;
        }
        //sesja(string nick,tcpklient,
        private:
        int sockfd, newsockfd, portno;
        socklen_t clilen;
        char buffer[256];
        struct sockaddr_in serv_addr, cli_addr;
        int n;
//      list<string> lista;
//      string user = null;
 };
int main(int argc, char *argv[])
{
        pthread_t wconnect;
        sesja *connect = new sesja;
        pthread_create(&wconnect,NULL,connect->run,NULL);
        //pthread_create(&wconnect,NULL,run,NULL);
        return 0;
}

Po kompilacji poleceniem: g++ -Wall start.cpp -g -o start.exe -lpthread
wyskakuje mi taki o to error:

start.cpp: In function ‘int main(int, char)’:
start.cpp error: argument of type ‘void* (sesja::)()’ does not match ‘void* ()(void)’**

Wygląda jak bym miał błędne rzutowanie ale np tutaj mam tworzenie wątka podobne a kompilacja przebiega prawidłowo.

 
#include <pthread.h>
#include <unistd.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
void* NewThread(void* arg)
{
        int id = *static_cast<int*>(arg);
        for (int i = 0; i < 3; i++)
        {
                std::cout << id << " " << std::flush;
                sleep(1);
        }
        return NULL;
}
int main()
{
        pthread_t thread;
        int id1 = 1;
        if (pthread_create(&thread, NULL, NewThread, (void *)(&id1)))
        {
                std::cerr << "bład podczas tworzenia watku nr 1" << std::endl;
                exit(1);

        }
        pthread_detach(thread);
        int id2 = 2;
        if (pthread_create(&thread, NULL, NewThread, (void *)(&id2)))
        {
                std::cerr << "bład podczas tworzenia watku nr 2" << std::endl;
                exit(1);
        }
        pthread_detach(thread);
        pthread_exit(NULL);
}

Proszę o pomoc w rozwiązaniu problemu.

1

w klasie Sesja zrób metodę statyczną, która będzie odpalać twoją metodę z klasy:

class Sesja
{
...
static void static_run(void param)
{
(Sesja*)param->run();
}
}

i jako parametr do wątku podawaj wskaźnik na klasę na której chcesz wykonać a jako funkcję Sesja::static_run.

0

Faktycznie zadziała ale problem wtedy mam ze zmiennymi musiałbym ustawić je jako statyczne. Tak czy inaczej nie za bardzo moge to zrobić bo z metody run bede chciał odpalać kolejny wątek do nasłuchiwania gniazda i problem rodzi się taki ze wątków ma się tworzyć tyle ile klientów miejać metody statyczne nie jestem w stanie tego w ten sposób rozwiązać.Tym bardziej żę pewnie listens to bedzie metoda innego obiektu. Więc moje pytanie brzmi czy nie mogę uruchomić takiego wątku bez metod statycznych?

0

nie zrozumiałeś do końca. dam ci przykład na wątkach na windowsa:

#include <stdio.h>
#include <windows.h>

volatile int koniec = 0;

class Sesja
{
public:
  static DWORD RUN(void* p)
    {
      return reinterpret_cast<Sesja*>(p)->run();
    }

  Sesja(int jakiespole): jakiespole(jakiespole) {}
protected:
  int jakiespole;
  virtual DWORD run()=0;
};

class A: public Sesja
{
public:
  A(int _): Sesja(_) {}
private:
  DWORD run()
    {
      printf("klasa A wypisuje wartosc jakiespole: %d\n",jakiespole);
      ++koniec;
    }
};

class B: public Sesja
{
public:
  B(int _): Sesja(_) {}
private:
  DWORD run()
    {
      printf("klasa B wypisuje wartosc jakiespole: %d\n",jakiespole);
      ++koniec;
    }
};

int main()
{
  Sesja* ses1 = new A(2);
  Sesja* ses2 = new B(7);

  CreateThread(0,0,(LPTHREAD_START_ROUTINE)Sesja::RUN,(void*)ses1,0,NULL);
  Sleep(1); // zeby sobie zdazyl spokojnie wypisac na ekran
  CreateThread(0,0,(LPTHREAD_START_ROUTINE)Sesja::RUN,(void*)ses2,0,NULL);

  // czekanie na watki
  while (koniec!=2)
    Sleep(1);

  delete ses1;
  delete ses2;
  return 0;
}

problem synchronizacji wątków powinien być w tym przykładzie rozwiązany inaczej, chciałem jednak żeby było jak najprościej

0

Dziękuje chyba już łapie:) - zaraz będę testował

0

możesz się pokusić (w zasadzie powinieneś) o zrobienie metody w stylu:
void runinthread() // wymysl madrzejsza nazwe
{
CreateThread(0,0,(LPTHREAD_START_ROUTINE)Sesja::RUN,(void*)this,0,NULL);
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1