Newsgroup: it.comp.lang.c++
Titolo: VOLATILE

Chi mi sa spiegare cosa richiedo al compilatore quando dichiaro una
variabile VOLATILE?
Ho cercato di leggere qualcosa a riguardo ma non ha cambiato piu' di
tanto la comprensione.
Infatti leggevo:"
<keyword volatile>. Tale keyword serve ad informare il compilatore che
una certa variabile cambia valore in modo aleatorio e che di
conseguenza il suo valore va riletto ogni volta che esso sia
richiesto"
Che significa che "il suo valore va riletto ogni volta che esso sia
richiesto"?
Esiste un fase di richiesta e una di lettura di una variabile???
Grazie
~Guybrush~

Esiste un fase di richiesta e una di lettura di una variabile???
Normalmente il compilatore assume che nessuno vada a cambiare le
variabili fra una istruzione e la successiva.
Se scrivi
   int x;
   void foo()
   {
     int a=x;
     int b=x;
     ...
   }
Il compilatore e' libero di leggere il valore di x una volta sola
e di memorizzarlo nelle due variabili locali. Se pero' scrivi:
   int x;
   void bar();
   void foo()
   {
     int a=x;
     bar();
     int b=x;
     ...
   }
allora il compilatore deve necessariamente rileggere il valore
visto che x e' una variabile globale e non puo' sapere cosa viene
fatto dalla funzione "bar()" (in particolare questa potrebbe
benissimo cambiare il valore di x).
Se dichiari una variabile "volatile" allora informi il compilatore
che qualcuno, in qualunque momento e in modo "asincrono" potrebbe
cambiare il valore della variabile. Il caso classico e' una variabile
che viene cambiata da un altro thread del tuo programma oppure dal
sistema operativo o dall'hardware...
   volatile int count=0;
   ...
   async_read(buffer,sz,&count,my_file); // I/O asincrono
   ...
   // Altre operazioni
   ...
   // Attesa completamento
   while (count==0)
     Sleep(1);
In questo caso (in cui mi sono inventato una async_read) se
non ci fosse la parola "volatile" il compilatore sarebbe
autorizzato a generare un codice macchina del tipo
   1 se count!=0 vai a 4
   2 chiama Sleep(1)
   3 torna a 2
   4 ...
Il test deve infatti farlo perche' ha chiamato una funzione
(async_read) passando l'indirizzo della variabile e questa
funzione potrebbe averne cambiato il valore... ma non e'
pero' tenuto a ripeterlo visto che le variabili non
cambiano spontaneamente (tranne quelle "volatile").
HTH
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

Esiste un fase di richiesta e una di lettura di una variabile???
Ci possono essere casi (chi ha mai usato "volatile" alzi la mano) in
cui una variabile venga modificata da agenti "esterni" al tuo
programma (caso tipico dell'hardware), per cui il compilatore non puo'
fare assunzioni sulla staticita' del valore di questa variabile e deve
leggerne il valore ogni volta, perche' tra una lettura e l'altra il
valore potrebbe essere stato aggiornato.

(chi ha mai usato "volatile" alzi la mano)
Mano alta.
Le variabili, oltre che dai libreschi harware che lavorano in memoria,
potrebbero essere modificate anche da altri thread.
Visto che costa cosi' poco by-passare le ottimizzazioni, in certi casi
puo' valerne anche la pena. Visto anche le ottimizzazioni aggressive
di certi compilatori. 
Quanto meno comunichi qualcosa a chi dovra' leggere il nostro codice.
+++
Scope Globale
volatile bool b = true;
Thread 1
while(b)
  faccio_qualcosa();
Thread 2
if ( strcmp(papero, "ciccio") == 0 )
	b = false;
-- 
Tieni per te il Papero se vuoi la mia email
Non usi la Papero Template Library? Male.
Sito Papero -> 
http://utenti.tripod.it/papero

Mano alta.
Non dubitavo sul fatto che qualcuno l'avesse usata.
Ci tenevo ad evidenziare il fatto che il suo uso non e' cosi'
frequente.

 Ci possono essere casi (chi ha mai usato "volatile" alzi la mano) in
E' un'ora che la tengo alzata ma non te ne sei ancora accorto, posso abbassarla?
--
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

E' un'ora che la tengo alzata ma non te ne sei ancora accorto, posso abbassarla?
Pensavo volessi andare in bagno...

e' cosi' frequente.
Uh... non mi ero accorto della chiamata.
Anche io ho ogni tanto a che fare con volatile (scrivendo
codice multithread e' qualcosa che non si puo' ignorare).
Anche chi lavora con un singolo thread ma con interrupt
non puo' ignorare il termine "volatile".
Un altro caso in cui mi e' capitato di usare "volatile"
e' stato con un compilatore C per sistemi embedded
quando abbiamo usato delle istruzioni assembler inline
che modificavano una variabile ... il compilatore non
analizzava cosa venisse fatto nel codice inline (non
e' sicuramente tenuto a farlo) e il risultato era che
nel codice seguente veniva usato il valore "vecchio"
della variabile invece di quello modificato.
In ogni caso credo che il codice multithread stia
diventando un qualcosa di molto comune, e la comprensione
delle problematiche che comporta (incluso "volatile")
secondo me diventa piu' importante ogni giorno che passa.
A quanto ho sentito una delle prossime direzioni di sviluppo
del C++ standard sara' definire esattamente quali sono le
garanzie fornite dal linguaggio e dalla libreria standard
in questi contesti in modo da fornire uno terreno solido
di base su cui affrontare il problema della programmazione
concorrente.


Vi invito a leggere i recenti thread a proposito di "volatile" su
comp.lang.c++.moderated ; in particolare si evince che, a meno di
garanzie specifiche e non standard del fornitore del compilatore, in
ambito multi-threaded "volatile" non e' di particolare aiuto,
principalmente perche' manca una garanzia sull'atomicita' delle
operazioni compiute sulla variabile dichiarata volatile.
Ciao,
Nicola

 wrote in message
news:3AED4E65...@divalsim.it...

Vero. Infatti gli accessi vanno comunque protetti con dei mutex o degli
spinlock. Ma nel caso di una statiche (all'interno di una funzione)
l'ottimizzatore puo' verificare che non esistono alias e "ottimizzare" gli
accessi anche attraverso chiamate a funzioni (quelle di sincronizzazione,
appunto). Ergo volatile.



E' ovvio che volatile nel caso di multithread non e' da solo
sufficiente visto che e' necessario avere delle garanzie di
atomicita' su quando si effettuano le operazioni di scrittura
su queste variabili. Sarebbe diverso se le operazioni di
scrittura su variabili dichiarate volatile fossero garantite
atomiche dallo standard. Questo pero' non e' vero.
Io ad esempio su Windows uso solo InterlockedExchange visto
che la documentazione Win32 garantisce che operazioni di lettura
da long correttamente allineati sono atomiche e InterlockedExchange
e' una operazione di scambio garantita atomica (anche su macchine
multiprocessore).
L'uso di "volatile" pero' resta obbligatorio... pena il rischio
di vedersi "ottimizzare" la lettura della variabile condivisa.
Quella lettura e' atomica perche' questa e' una garanzia della
piattaforma.
Sicuramente a oggi le parti di codice che utilizzano "volatile"
con multithreading non sono portabili... ma questo perche' non
e' portabile il multithreading in C/C++ (anche se a quanto ho
sentito questa e' sicuramente una delle prossime aree su cui
il comitato lavorera').
Il modifier "volatile" e' portabile e ha un suo senso comunque...
ad esempio potrebbe essere usato con variabili modificate
da interrupt.
Andrea
-- 
Posted from [151.99.250.40] 
via Mailgate.ORG Server - 
http://www.Mailgate.ORG

ambito multi-threaded "volatile" non e' di particolare aiuto,
Se lo scrittore e' uno solo e la variabile e' "semplice", non vedo la
necessita' di proteggere l'accesso alla variabile. 
In fondo il codice del lettore in assembler sara' molto probabilmente
tradotto con qualcosa del tipo:
// pseudo asm
operatore_and registro, variabile, variabile
jump se_stato_bit_zero_alto
un' interruzione appena prima del jump e' ininfluente. In questo caso
specifico (un solo scrittore, variabile contenibile in un registro
usata per un test) la pretesa necessita' di atomicita' e' inutile. In
questo caso il modificatore di tipo "voltatile" e' necessario e
sufficiente.


Io ad esempio su Windows uso solo InterlockedExchange 
Che e' un leggero wrapper su una istruzione specifica degli attuali
processori x86. In questo caso preferisco scrivere direttamente
l'istruzione in assembly.


 sufficiente.
Occhio che quando si parla di atomicità di accesso si intende anche sincronismo
con processori concorrenti. Inoltre la definizione di "variabile che sta in un
registro" e' piuttosto vaga, se ti interessa la portabilità. Per il resto sono
d'accordo.


 l'istruzione in assembly.
Non se intendi dire che la scrivi inline con asm. Se intendi dire che ti scrivi
una tua versione di InterlockedExchange invece ok.
Il motivo e' che se usi asm in una funzione praticamente e' come inserire una
pragma che disabilita in l'ottimizzatore su quella funzione.


registro" e' piuttosto vaga, se ti interessa la portabilitą. 
Direi che int va piu' che bene per avere una variabile portabile da
utilizzare come oggetto di sincronizzazione.


pragma che disabilita in l'ottimizzatore su quella funzione.
Uhm, interessante. Non ci avevo mai pensato.
In realta' se usi il VC++ puoi decidere di usare funzioni "nude",
cioe' senza prologo e senza epilogo, che direi sono molto vicine alle
funzioni inline. Non portabile per non portabile.


 utilizzare come oggetto di sincronizzazione.
Salvo che non e' sempre vero.
Non c'e' garanzia che una variabile int sia letta/scritta in maniera atomica.
Che poi la maggior parte delle implementazioni lo faccia per default e' un'altro
discorso. Ma ci sono architetture in cui l'alignement non e' stringente e
compilatori (soprattutto embedded) che non lo esegeguono per default. I
compilatori "comuni" invece per default lo fanno ma ... puoi anche
disabilitarlo.


Non c'e' garanzia che una variabile int sia letta/scritta in maniera atomica.
Perche' dici questo. Mostrami un controesempio. 
Insomma cosa e' un intero?
Mostrami un processore in cui non puoi leggere un intero in una botta,
e io ti diro' che quello non e' un intero. Un processore a X bit, ha
gli interi di X bit per definizione.
Potresti (in teoria) non poterlo leggere/scrivere in maniera atomica
dalla memoria se e' a cavallo di due pagine di memoria in un sistema
paginato (ma non puo' succedere su un Intel con un canale di bus a 64
bit), o chissa' in che diavolo di sistema.
In quel sistema (se fatto cosi' male) non avrai pero' ne
InterlockInterChange, e CriticalSection, ne niente. Probabilmente.
In realta' i sistemi embedded sono fatti meglio dei computer "seri"
(oltre costare meno), In alcuni processori jap a 16 bit (per esempio)
un indirizzo di memoria indirizza una variabile di 16 bit (char e int
a 16 bit quindi).
