Newsgroup: it.comp.lang.c++
Titolo: Metodi di classi come thread ???

Ciao a tutti
sto cercando di eseguire come thread una funzione membro di una classe e 
sto diventando pazzo :-)  
Sto programmando in Linux con la libpthread (POSIX), ho capito che il 
problema e' che la pthread_create() si aspetta un puntatore ad una funzione 
e che un puntatore ad un metodo di una classe e' un'altra cosa. Ma allora 
come si fa???
Ho letto in un altro post di dichiarare un elemento funzione static che 
chiama il metodo ma non funziona neanche cosi' , mi da' l'errore :
Player.C:53: cannot declare member function `Player::Sensor_driver ()' 
to have static linkage
Player.C: In function `void Player::Sensor_driver ()':
Player.C:53: cannot call member function `Player::acquire ()' without 
object
io non ci capisco piu' nulla, c'e' qualcuno che sa aiutarmi?
Bye, Carlo

 come si fa???
Esempietto giocattolo scritto al volo giusto per rendere l'idea:
 class my_thread
 {
    public:
    void* run();
    void spawn()
 };
 extern "C" {
  void* run_thread( void* ptr )
  {
    return reinterpret_cast<my_thread*>(ptr)->run();
  } 
 }
 
 void my_thread::spawn()
 {
     pthread_t tid;
     pthread_create( &tid, 0, run_thread, this );
 }
In sostanza, quello che accade è che il quarto argmento di pthread_create
viene passato a run_thread, che lo "reinterpreta" come my_thread* ed
esegue il metodo desiderato all'interno del thread appena creato.
Il riferimento a pthread è OT qui. La tecnica usata però è
sufficientemente generica per essere discussa in questa sede, credo.
Max

"Carlo Mi8" ha scritto:
io ho fatto cosi' 
(ti tolgo la gestione delle eccezioni per chiarezza)
do_func() e' friend di App
App::text e' static
struct params {
    const std::string* src;
    std::string* dest;
};
extern "C" {
void* do_func(void*);
};
//...
void App::func(){
    text->Freeze();
    std::string* Text = new std::string;
    Text->reserve(text->GetLength());
    Text->assign(text->GetText(0, -1));
    std::string *Coded = new std::string;
    volatile params Params;
    Params.src  = Text;
    Params.dest = Coded;
    /* nuovo thread per il coding */
    pthread_t thread;
    pthread_create(&thread, NULL, do_rot13, (void*)&params);
    pthread_detach(thread);
}
extern "C" {
  void* do_func(void* Arg){
    params* arg  = reinterpret_cast<params*>(Arg);
    arg->dest->resize(arg->src->length());
    Code(arg->src->begin(), arg->src->end(), arg->dest->begin());
    App::text->DeleteText(0,-1);
    App::text->SetText(*(arg->dest));
    App::text->Select(-1,-1);
    App::text->Thaw();
    delete (arg->src);
    delete (arg->dest);
    pthread_exit(0);
  }
};
in pratica faccio un nuovo thread *all'interno* della funzione membro e 
poi ritorno.
il thread va avanti da solo, cancella le risorse avute ad esce.
se poi avessi usato auto_ptr, non avrei neanche dovuto chiamare i due 
delete. (prima o poi lo faro' :)

     return reinterpret_cast<my_thread*>(ptr)->run();
Grazie mille, ora ho un'idea di quello che dovrei fare, non ho ancora ben 
capito questa istruzione, e' una funzione di libreria? quale?
Thanx, Carlo

 wrote in message
news:2D3%6.314$_F1....@news2.tin.it...

In C++ l'operatore di cast del C e' supportato ma abbastanza sconsigliato. Viene
sostituito dai cast del C++ che sono static_cast, reinterpret_cast, const_cast e
dynamic_cast. Non sono funzioni e, anche se lo sembrano, neppure template. Fanno
parte del linguaggio. Cercati un buon reference.
Comunque nel caso suddetto praticamente puoi "leggere" la cosa cosi':
return ((my_thread*)ptr)->run();
--
Andrea Ferro
---------
Brainbench C++ Master. Scored higher than 97% of previous takers
Scores: Overall 4.46, Conceptual 5.0, Problem-Solving 5.0
More info 
http://www.brainbench.com/transcript.jsp?pid=2522556

 come si fa???
In realtà non andrebbe fatto...!!!  ;-)
Voglio dire che dal punto di vista della programmazione ad oggetti non è
troppo bello associare a una funzione membro un thread, perchè in questo
modo il programmatore deve diventare pazzo con le sincronizzazioni.
Adottando la tua soluzione, si ha un oggetto in cui tutte le funzioni membro
sono eseguite in un thread, mentre un metodo, per convenzione, non viene
chiamato da nessuno ma viene eseguito in un thread separato.
Se un giorno la tua applicazione multithread dovesse diventare
un'applicazione distribuita (un po' di software su una macchina e un po' su
un'altra) la tua soluzione non è più praticabile. Sarebbe molto meglio avere
un oggetto su una macchina e un altro su una macchina diversa piuttosto che
avere un metodo di un oggetto di qua e un altro metodo di là...
La cosa ideale sarebbe quindi avere un oggetto per cui *tutti* i metodi
vengono automaticamente eseguiti in un altro thread. Questa è la soluzione
più naturale: ogni oggetto ha un suo thread, così non è più nemmeno
necessario la sincronizzazione tra metodi diversi dello stesso oggetto.
Purtroppo tale soluzione è un po' laboriosa in C++ (e in qualunque altro
linguaggio tranne Eiffel...) perchè occorrerebbe che ogni metodo di quella
classe (che viene per forza di cose eseguita nel thread del chiamante)
semplicemente mettesse la richiesta in una coda, da cui venisse prelevata
dal nostro thread "della classe" e eseguita.
Per maggiori dettagli vedi il libro di Meyer (Object Oriented Software
Construction) al capitolo dedicato a SCOOP, oppure l'artricolo di Pescio su
Computer Programming ("Oggetti e thread") che lo spiega nel dettaglio.
Saluti
--
Daniele Pallastrelli
pallas...@ieee.org
----------------------------------------------------------------------------
-------
In theory, there's no difference between theory and practice, but in
practice there is.

 
Ahh ecco mi pareva, purtroppo ho ripreso in mano il C++ da poco ed 
evidentemente il mio manuale non e' molto aggiornato perche' non ne accenna 
neppure :-)
Thanx, Carlo

 dettaglio.
Quel tipo di approccio č illustrato anche in questo articolo:
 
http://www.cs.wustl.edu/~schmidt/PDF/Active-Objects.pdf
Max