Newsgroup: it.comp.os.linux.development
Titolo: Aiutino con i thread in c++

Ho letto molto sul web in merito. Ci sono varie librerie che permettono di
usare i thread in C++ ma voglio scrivere direttamente il codice che mi
permette di far ciò nel mio programma. Nel file mizio.h ho tolto dalla
classe le due funzioni che vengono eseguite dai thread risolvendo
parecchi problemi di compilazione. Il problema però è che alcune strutture
dati dichiarate nella prima funzione mi servono nella seconda ed ovviamente
g++ mi dà undeclared. Inoltre ho bisogno del puntatore this in una di queste
funzioni e anche qui, perchè ho tolto queste funzioni dalla classe ottengo
errori. Come posso fare ?
Questo è il file mizio.h:
#include "mizio_centralwidgetbase.h"
#define SERVER_PORT 80
class Mizio : public KMainWindow
{
    Q_OBJECT
public:
    Mizio();
    KAboutApplication *aboutMizio;
    virtual ~Mizio();
protected:
class Mizio_CentralWidgetBase *Mizio_View;
private slots:
        void ShowAboutWindow();
        void Mizio_Exit();
        void Retrieve();
        void Check_Proxies();
        void Export();
};
// Queste sono le due funzioni tolte dalla classe che i thread eseguono
        void* Mizio_Server( void* );
        void* Mizio_Client( void* socket );
#endif // _MIZIO_H_
Questo è parte del file mizio.cpp:
void Mizio::Check()
{
        Mizio_View->Button_Check->setEnabled ( false );
        pthread_t Mizio_Server_Thread;
        pthread_create( &Mizio_Server_Thread, NULL, Mizio_Server, (void*)NULL );
        QListViewItemIterator it( Mizio_View->mizio_listview );
        while ( it.current() )
        {
                //check->Send_GET_Request ( Local_Address , Mizio_View->mizio_listview ,
it.current()->text(0) , it.current()->text(1) );
                ++it;
                //Aggiungere il codice che controlla se i thread hanno finito e chiude la
porta 80 :-)
                //Mizio_View->Button_Export->setEnabled ( true );
        }
}
void* Mizio_Server ( void* dummy )
{
  pthread_t Client_Thread;
  int Server_Socket;
  int accepted_socket;
  int size;
  struct sockaddr_in port_addr, accept_addr;
  int set_opt = 1;
  fd_set read_set;
  int ready_fd;
  /* set up the socket on the server port */
  port_addr.sin_family = AF_INET;
  port_addr.sin_addr.s_addr = htonl( INADDR_ANY );
  port_addr.sin_port = htons( SERVER_PORT );
  Server_Socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
  setsockopt( Server_Socket, SOL_SOCKET, SO_REUSEADDR, (char*)&set_opt,
sizeof( set_opt ) );
  if ( bind(Server_Socket, (struct sockaddr*)&port_addr, sizeof( port_addr
)) < 0 )
  {
  //KMessageBox::error(Mizio_View, "Can't open port 80, maybe another
program\nis using it or you are not root !");
  return;
  }
  for( ;; )
  {
    listen( Server_Socket, 5 ); /* wait for the client to try to connect */
        FD_ZERO( &read_set );
    FD_SET( Server_Socket, &read_set );
    do {
      ready_fd = select( Server_Socket+1, &read_set, NULL, NULL, NULL );
                }
    while ( ready_fd <= 0  ||  !FD_ISSET( Server_Socket, &read_set ) );
    /* a client has connected.  Accept their connection and create a thread
to serve the client */
    size = sizeof( accept_addr );
    accepted_socket = accept( Server_Socket, (struct sockaddr*)&accept_addr,
&size );
    pthread_create( &Client_Thread, NULL, Mizio_Client,
(void*)accepted_socket );
}
  }
  void* Mizio_Client ( void* socket )
{
        char HTTP_Headers[1024];
        //mi serve la struttura accept_addr ma ho errore se tolgo le //
        //printf ("New conn from %s on socket %d\n",
inet_ntoa(accept_addr.sin_addr), socket);
        while ( read( (int)socket, HTTP_Headers, 1024 ) > 0)
        {
                printf ("%s",HTTP_Headers);
        }
        close( (int)socket );
    pthread_exit( NULL );
}
A questo punto mi sembra chiaro che debbo includere le due funzioni
nella classe Mizio ma se le includo il compilatore mi da errore sul codice
con pthread_create.
Grazie
-- 
Colossus

Mi rendo conto di non essere stato molto chiaro. Il puntatore
this che mi occorre è quello del qwidget su cui poggia 
la GUI con i pulsanti:
//KMessageBox::error(Mizio_View, "Can't open port 80, maybe another
program\nis using it or you are not root !");
Se tolgo i doppi slash ho l'errore Mizio_View undeclared. Come posso
bypassare questo ?
Bye,
Colossus

 errori. Come posso fare ?
Questo  l'ho   scritto  tempo,  non   e`  molto  testato  ;)   Ti  basta
specializzare e definire il metodo  main. Poi al thread passi quello che
vuoi.
#ifndef THREAD_H
#define THREAD_H 1
extern "C" {
#include <pthread.h>
}
/** Classe astratta Thread. Classe astratta che contiene i meccanismi 
 * di base per la gestione dei thread. Il parametro T indica il tipo 
 * accettato dalla funzione main (corpo del thread), il parametro R 
 * indica il tipo di ritorno della funzione main.
 */
template <typename T, typename R> class Thread {
	private:
		/* @var Thread id */
		pthread_t tid;
		/* @var Stato del thread */
		int state;
		enum {THREAD_FINISHED, THREAD_RUNNING, THREAD_CANCELLED};
		/* La funzione statica helper non riceve this, quindi
		 * devo fare in modo di passarglielo io.
		 */
		struct arg_t {
			Thread<T, R> *self;
			T args;
		} args;
		R ret_;
		/** Funzione helper. Funzione statica che fa da proxy
		 * per la funzione pthread_create() Deve essere statica, 
		 * altrimenti non potrebbe essere passata a
		 * pthread_crete.
		 *
		 * @param arg struttura arg_t castata a void *
		 *
		 * @return per compatibilita` con pthread_create. Il
		 * valore restituito e` sempre NULL.
		 * */
		static void *helper(void *arg) {
			arg_t *p = reinterpret_cast<arg_t *>(arg);
			p->self->state = THREAD_RUNNING;
			p->self->ret_ = p->self->main(p->args);
			p->self->state = THREAD_FINISHED;
			pthread_exit(NULL);
		};
		virtual R main(T) = 0;
		static void yield() { sched_yield(); }
	public:
		Thread(): tid(0), state(THREAD_FINISHED) { args.self = this; }
		virtual bool start();
		virtual bool start(T);
		virtual bool join();
		virtual void cancel();
 
		R ret() { return ret_; }
		void set_arg(T a) { args.args = a; }
};
template <typename T, typename R> bool Thread<T, R>::start() {
	if (state != THREAD_FINISHED)
		return false;
 
	void *p = reinterpret_cast<void *>(&args);
	if (pthread_create(&tid, NULL, helper, p) == 0)
		return true;
	else
		return false;
}
template <typename T, typename R> bool Thread<T, R>::start(T a) {
	if (state != THREAD_FINISHED)
		return false;
 
	set_arg(a);
	return start();
}
template <typename T, typename R> bool Thread<T, R>::join() {
	/* May block! */
	if (tid == 0)
		return false;
 
	if (pthread_join(tid, NULL) == 0) {
		tid = 0;
 
		return true;
	} else {
		tid = 0;
 
		return false;
	}
}
template <typename T, typename R> void Thread<T, R>::cancel() {
        if (state != THREAD_RUNNING)
                return;
	pthread_cancel(tid);
	state = THREAD_CANCELLED;
}
#endif /* THREAD_H */
HTH,
Luca
-- 
Home: 
http://kronoz.cjb.net
K.R.O.N.O.S
Kinetic Replicant Optimized for Nocturnal Observation and Sabotage

 vuoi.
Grazie mille, sei stato molto gentile. Purtroppo il tuo codice
è ostico da capire per un principiante come me, comunque
ho fatto un copia e incolla e l'ho messo insieme agli altri
pezzi di codice che raccolgo qua e là, in futuro quando
sarò diventato più esperto gli darò uno sguardo volentieri !
Grazie,
-- 
Bye,
Colossus