Newsgroup: it.comp.lang.c++
Titolo: cos'è un "singleton"?

ciao a tutti; ho sentito alcune volte parlare di questo "singleton" (si
scrivera' cosi'? boh!) senza mai capirne il significato! ci sarebbe
qualcuno cosi' gentile da spiegarmi cos'e' e come si usa?
--
Ciao by Beppe

qualcuno cosi' gentile da spiegarmi cos'e' e come si usa?
Il pattern chiamato "singleton" e' quello che rappresenta la
necessita' di avere una sola istanza di un oggetto a cui
diversi altri oggetti accedono.
Un esempio comune e' quello di un oggetto "giornale di bordo"
che registra dei messaggi su delle operazioni effettuate...
diversi oggetti vorranno usare il giornale di bordo per
registrare ma e' importante che questo giornale sia unico in
tutto il programma.
In molti linguaggi per i singleton si usano semplicemente
variabile globali. In C++ la cosa e' piu' complessa per
colpa della logica dell'inizializzazione delle istanze
statiche non locali.
Un esempio classico di implementazione di un singleton
in C++ e':
/// GiornaleDiBordo.h
class GiornaleDiBordo
{
  public:
    static GiornaleDiBordo *get_istance();
  ...
};
/// GiornaleDiBordo.cpp
GiornaleDiBordo *GiornaleDiBordo::get_instance()
{
  static GiornaleDiBordo instance;
  return &instance;
}
/// Main.cpp
   ...
   GiornaleDiBordo::get_instance()->
     Scrivi("Arrivati in porto");
   ...
HTH
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

 statiche non locali.
Per colpa o... per merito? :-)
Ad ogni modo, può essere resa più complessa, ma le variabili globali restano
comunque una valida alternativa.
Ciao
Domenico

 }
solitamente una cosa del genere comporterebbe degli errori in quanto si
ritorna un riferimento ad una variabile locale. E' il fatto che tale
variabile sia in questo caso "static" che modifica le cose e permette cio'?
Thanks of all!
--
Ciao by Beppe

variabile sia in questo caso "static" che modifica le cose e permette cio'?
Si... "static" in questo contesto indica che l'oggetto instance
verra' creato solo la prima volta che viene chiamata la funzione
get_instance e restera' valido per tutte le chiamate successive.
E' una specie di variabile globale ma con due differenze:
  1) Il C++ garantisce il momento esatto in cui sara' costruita
     (ovvero alla prima chiamata di get_instance)
  2) E' visibile solamente all'interno della funzione
Nota che in C++ la parola "static" puo' avere anche altri
significati quando e' usata in altri contesti.


 comunque una valida alternativa.
In realta' non sono in alternativa: il singleton ha senso solo se si
pone il problema dell'ordine di inizializzazione e se e' necessario
garantire che di una classe non vengano costruite piu' di n istanze,
dove n di solito e' 1, ma non necessariamente.
Le variabili globali non garantiscono nessuna delle due condizioni.
Ciao,
Nicola

Il problema che il singleton tradizionale non risolve, ne' nella
versione di Meyers da te illustrata, ne' in quella di Gamma & c., di
poco differente, e' la garanzia dell'ordine di distruzione tra singleton
interdipendenti. Per questo motivo preferisco restituire un puntatore
intelligente dotato di contatore dei riferimenti.
Ciao,
Nicola



Una tecnica largamente usata per questo tipo di esigenze è quella di avere
un "object manager", sul quale i vari singleton si possano registrare al
momento della propria creazione, ed essere successivamente distrutti
nell'ordine appropriato e al momento opportuno.
Max

Ma questo crea un legame inutile, che con il reference counting non e'
necessario. Per essere equivalente il tuo object manager deve conoscere
le interdipendenze tra i diversi singleton, e addio modularita'.
Ciao,
Nicola

On Mon, 4 Dec 2000, Nicola Musatti wrote:

Io pensavo a un object manager piuttosto elementare che si limitasse a
tener traccia degli oggetti creati e provvedere alla loro distruzione
nell'ordine inverso in cui sono stati creati, che è possibile realizzare
anche senza imporre dipendenze o rapporti di parentela tra le classi dei
vari singleton e senza iniettare nell'object manager stesso alcuna nozione
esplicita relativa al tipo degli oggetti coivolti (tipicamente si usano
liste di puntatori a classi wrapper template o liste di void* combinati
con puntatori a instanziazioni di funzioni template "distruttrici").
Max

intelligente dotato di contatore dei riferimenti.
Ho discusso della cosa con Meyers in persona. L'esempio che
ho portato richiede poche linee di codice, e' di immediata
comprensione anche per chi non ha mai sentito parlare di
singleton e risolve il problema di riferimenti durante la
fase di inizializzazione (il caso piu' frequente).
Come tu fai notare non si risolve correttamente il problema nel
caso di riferimenti durante la chiusura. Per risolvere questo
problema, ad esempio, si puo' utilizzare la tecnica che
Marshall Cline chiama "nifty counter" e che viene mostrata
oltre che in "C++ FAQs" anche in "The C++ Programming Language"
quando si parla dell'inizializzazione di std::cin e std::cout.
Anche quella tecnica ha pero' delle controindicazioni (tanto
per cambiare non esiste la pallottola d'argento) e di questo
si sono accorti sia Stroustrup (che cita il problema del
paging iniziale nel suo libro) che Meyers che ha deciso di
rimuovere l'esempio nella seconda edizione in quanto una
discussione seria dei pro e dei contro delle possibili tecniche
avrebbe appesantito troppo l'argomento nel suo libro.
"C++ FAQs" mostra un po' di esempi di approccio, incluso quello
di "abbandonare" i singleton sullo heap senza che venga mai
chiamato il distruttore:
  Registry *Registry::get_instance()
  {
    Registry *instance_ptr=new Registry;
    return instance_ptr;
  }
Anche se puo' far storcere il naso questa soluzione e' spesso
decente (capita di frequente che esistano dei singleton di
tipo "registry globale" in cui una serie di istanze o di
classi si registrano... questi registry non hanno nulla di
interessante da fare nel distruttore).
Io non mi trovo comunque a mio agio con un memory leak
by design :DDD
La tecnica degli smart ptr con reference counting mi piace
(io sono un tifoso del reference counting... a morte i garbage
collectors!!!!) ma, come al solito, ha pregi e difetti e
fra questi ultimi c'e' la complessita'.
Io volevo soltanto fare un semplice esempio di
implementazione possibile... non certamente esaurire
l'argomento.


 l'argomento.
Per carita', ci vorrebbe un libro intero!
Ciao,
Nicola