Newsgroup: it.comp.lang.c++
Titolo: No limits C++

Ciao a tutti!
Posto il messaggio con questo Subject, in memoria della compianta newsletter 
"C++ informer" del Dr. Pescio.
In effetti il problema che vorrei risolvere penso che sia nello stile della 
rubrica a cui mi riferisco, che trattava (per chi non l'ha mai letta) di 
quei "trucchi" fantastici che ci si puo' immaginare con un po' di fantasia, 
giocando con i costrutti del C++.
Supponiamo di avere una classe base, esempio:
class Module
  {
  protected:
    Module( const std::string& name );
    ~Module() {...}
 
  private:
 
  };
Evidentemente, a causa del costruttore protetto, posso usare questa classe 
solo come base per altre classi derivate:
class MyModule: public Module
  {
  public:
    MyModule() : Module( "MyModule" ), aString( "Something" ) {...}
    ~MyModule() {...}
    ...
  private:
    std::string aString;
  };
Quando un oggetto di classe MyModule viene distrutto vengono chiamati 
nell'ordine:
MyModule::~MyModule()
MyModule::aString::~string() //sintatti contorta ma comprensibile :-)
Module::~Module()
(se non vado errato)
Quello che vorrei ottenere e' la possibilita' di inserire una porzione di 
codice che venga eseguita automaticamente quando l'oggetto viene distrutto, 
ma che si collochi prima dell'invocazione di MyModule~MyModule(), il tutto 
agendo solo sulla classe base Module.
Questo metodo mi permetterebbe di risolvere in modo elegante il seguente 
problema: la mia classe Module fa parte di un framework, e consente di 
creare classi concrete (MyModule) che sono "oggetti attivi", nel senso che 
i loro metodi vengono eseguiti su thread separati. Quando un oggetto 
:MyModule viene distrutto, prima di tutto devo permettere ai thread 
eventualmente attivi sui suoi metodi di terminarne l'esecuzione, perche' se 
invoco il distruttore di aString (ad esempio) prima che abbiano finito, ho 
dei comportamenti indefiniti. Quello che non vorrei fare e' dover imporre 
all'utente di inserire codice nel distruttore di MyModule.
Per ora non ho trovato nessuna soluzione accettabile, forse si puo' fare 
qualche cosa con l'operatore delete, ma questo funzionerebbe solo per gli 
oggetti allocati dinamicamente.
Grazie in anticipo per l'aiuto, e scusate la lunghezza.
Francesco.

 per gli oggetti allocati dinamicamente.
proprio in quella mailing list venne implementata la stessa cosa, al 
rovescio per i costruttori. cercala e vedi se ti va bene ( usava una 
classe proxy, se non ricordo male)

Enrico Foschini wrote:

Si, in realta' e' proprio quel numero che mi ha dato l'idea ;-)
Veniva sfruttata la lifetime di un temporaneo (classe Initializer credo) per 
eseguire "qualche cosa" quanto tutti i costruttori avevano terminato 
(serviva per eseguire un metodo virtuale, che il costruttore avrebbe 
linkato staticamente), pero' nel mio caso non lo posso applicare, dato che 
non si puo' definire un distruttore con parametri, tipo:
~Module( Finalizer F = Finalizer() );
(o almeno il gcc non me lo lascia fare)
Comunque credo che non possa bastare, perche' Finalizer::Finalizer()
verrebbe comunque eseguito appena prima del distruttore di Module,
quindi dopo MyModule::~MyModule() (nell'esempio).
In effetti mi ci sono scervellato per un po' :-)
Comunque grazie per il consiglio.
Se ti viene in mente qualche altra idea...
Ciao!

 Se ti viene in mente qualche altra idea...
ora che ci penso...
mi sa che hai un problema di design:
perche' devi inserire qualcosa in ~Module() a seconda del tipo 
ereditato? mi sembra che il posto migliore sia nel ditruttore della 
classe ereditata...
comunque puoi usare un trucco abb. semplice
<codice non testato>
class Module {
[...]
 protected:
  typedef void (*Finalizer)(void*); 
  Finalizer finalizer;
 // puntatore a funzione, puoi metterci quel che vuoi come parametri
  virtual set_finalizer(Finalizer f) { finalizer = f;}//
  virtual void finalize() { if (finalizer) finalizer();}
[...]
};
void do_stuff( void* buf);
class MyModule : public Module {
  MyModule(){
    set_finalizer(&do_stuff);
    // etc
  }
  ~MyModule() {
    finalize();
    // etc
  }
};

 [...]
Uhm?? In effetti e' la soluzione piu' ovvia...
In realta' e' proprio quello che volevo evitare, ma per spiegare il perche' 
devo andare un po' piu' nei dettagli del problema.
Nel mio sistema (framework) i moduli vengono scritti da un'utente, che 
sfrutta le API fornite dal mio codice. Cosi', ad esempio, l'utente della 
libreria potrebbe scrivere codice di questo tipo:
class MyModule : public Module
  {
  protected:
    void funct1_impl()
      { /* do something on local data */ }
    void funct2_impl(int x)
      { /* do something else on local data */ }
  public:
    Method<void> funct1;
    Method<int> funct2;  //il template e' pari al parametro di funct2_impl()
    MyModule() 
       : funct1( *this, &MyModule::funct1_impl ),
         funct2( *this, &MyModule::funct2_impl ) {}
    };
La libreria consente di scrivere codice di questo tipo (Method<> ridefinisce 
l'operatore () ):
{
MyModule mod;
mod.funct1();
//...
mod.funct2(10);
//...
}
Pero' le due "method call" in realta' fanno eseguire i due metodi di 
implementazione su due thread separati, senza bloccare il chiamante.
In piu' la libreria gestisce internamente la sincronizzazione dell'oggetto, 
nel senso che ogni thread attivato sui metodi *_impl acquisisce un mutex 
globale per l'oggetto Module prima di eseguire il corpo del metodo, e lo 
rilascia alla fine, cosi' da garantire l'atomicita' del metodo (nello stile 
dell'active object di Meyer).
Quando l'oggetto mod (nell'esempio) esce dallo scope del thread chiamante 
viene pero' chiamato il suo distruttore probabilmente prima che i thread 
che stanno eseguendo sui suoi metodi abbiano terminato!!!
La soluzione e' che anche il distruttore acquisisca il solito mutex prima di
fare alcunche', cosi' si puo' eventualmente porre in attesa finche' gli 
altri non hanno terminato.
Vorrei pero' evitare che chi scrive MyModule debba ricordarsi di invocare un 
metodo tipo "beforeDestroy()" (reso disponibile da Module) nel distruttore, 
perche' se si dimentica possono avvenire errori soltanto a tempo di 
esecuzione, ed in modo casuale!
Praticamente lo scopo dell'intero sistema e' rendere il piu' semplice 
possibile la programmazione concorrente, per cui il mio obiettivo e' fare 
in modo che l'utente debba occuparsi il meno possibile dei dettagli.
E' tutto :-)
Un amico, che tra l'altro ha scritto (e pensato) il core del sistema, mi ha 
suggerito di fare in modo che gli oggetti MyModule possano soltanto vivere 
nello heap, associati ad uno smart pointer specializzato che esegue 
beforeDestroy() prima di distruggerli. Per adesso non sono riuscito a 
trovare di meglio...
Ciao e grazie!
Francesco.

 adesso non sono riuscito a trovare di meglio...
piu' semplice sarebbe una factory, togliere i costruttori espliciti di 
module, e nascondere l'implementazione di Module con il Pimpl: ad esempio
class basemethod; // classe base vuota, solo per derivare Method<T>
template <typename T>
class Method: public basemethod{//...};
class Module {
  RealModule* pImpl;
public:
  Module():pImpl(0) {}
  void Assign( const basemethod& a, const basemethod& b){ 
    pImpl = RealModule::Create( a, b ); // crea un nuovo oggetto
  }
  [...]
  ~Module(){
    pImpl->Release();
  }
}
ovviamente il costruttore MyModule() sara'
  MyModule() :
         funct1( *this, &MyModule::funct1_impl ),
         funct2( *this, &MyModule::funct2_impl ) {
    Assign(funct1, funct2); 
  }
RealModule si occupera' dei due thread, e li gestira', cancellandoli 
quando avra' avuto il release
se pero' non puoi cambiare Method (anche se e' un cambiamento minimo), 
si puo' fare lo stesso, devi incapsulare Method<T> in un'altra classe 
che non fa altro che ereditare da basemethod e avere un Mehod<T> da 
richiamare per usarne le funzioni (una specie di decorator)

 adesso non sono riuscito a trovare di meglio...
piu' semplice sarebbe una factory, togliere i costruttori espliciti di 
module, e nascondere l'implementazione di Module con il Pimpl: ad esempio
class basemethod; // classe base vuota, solo per derivare Method<T>
template <typename T>
class Method: public basemethod{//...};
class Module {
  RealModule* pImpl;
public:
  Module():pImpl(0) {}
  void Assign( const basemethod& a, const basemethod& b){ 
    pImpl = RealModule::Create( a, b ); // crea un nuovo oggetto
  }
  [...]
  ~Module(){
    pImpl->Release();
  }
}
ovviamente il costruttore MyModule() sara'
  MyModule() :
         funct1( *this, &MyModule::funct1_impl ),
         funct2( *this, &MyModule::funct2_impl ) {
    Assign(funct1, funct2); 
  }
RealModule si occupera' dei due thread, e li gestira', cancellandoli 
quando avra' avuto il release
se pero' non puoi cambiare Method (anche se e' un cambiamento minimo), 
si puo' fare lo stesso, devi incapsulare Method<T> in un'altra classe 
che non fa altro che ereditare da basemethod e avere un Mehod<T> da 
richiamare per usarne le funzioni (una specie di decorator)
Per di piu', cosi' facendo, puoi anche gestire un pool di RealModule 
sullo  stack, aggiungendone magari altri solo se necessario 

 sullo  stack, aggiungendone magari altri solo se necessario
Aspetta, c'e' una cosa che mi sfugge: MyModule dovra' sempre ereditare da 
Module?
Perche' il problema mi sembra che rimanga...
Cioe': se MyModule ha un membro di tipo int* (ma qualsiasi cosa un po' 
complessa va bene) che viene allocato nel costruttore e liberato nel 
distruttore, di questo dato viene fatta la delete prima di eseguire 
~Module(), quindi quando ancora i funct_impl possono essere in esecuzione 
(e quindi lavorare sul dato).