Newsgroup: it.comp.os.linux.development
Titolo: variabili statiche nella shared memory

Ciao!
Su it.comp.lang.c++ mi hanno consigliato di postare qui, dicendomi che
questo problema e' risolvibile utilizzando le API di sistema. Eccolo:
#include <iostream.h>
#include <unistd.h>
void stat() {
  static int i = 0;
  cout << i << endl;
  i ++;
}
int main() {
  int pid = fork();
  if(pid == 0) {
    stat();
    stat();
    stat();
  }
  else {
    stat();
    stat();
    stat();
  }
  sleep(1);
}
L'output di questo programma e' sempre nella forma 012012, oppure
001212, o simili, in quanto i due processi generati dalla funzione
fork() non condividono la stessa variabile statica i.
Cosa si deve fare per rendere l'output del programma pari a 012345,
cioe' per far condividere ai processi la stessa variabile statica?

 cioe' per far condividere ai processi la stessa variabile statica?
Per far dividere i due processi la stessa variabile statica, basta usare la
clone o le funzioni della libreria pthread
[ghigo@therra tmp]$ cat p1.cc
#include <iostream.h>
#include <unistd.h>
#include <pthread.h>
void stat( ) {
  static int i = 0;
  cout << i << endl;
  i ++;
}
void * stat3( void * ){
        stat( );
        stat( );
        stat( );
}
int main() {
  pthread_t     t1,t2;
  pthread_create(&t1,0,stat3,0);
  pthread_create(&t2,0,stat3,0);
  sleep(1);
}
[ghigo@therra tmp]$ g++  -lpthread  -o p1 p1.cc
[ghigo@therra tmp]$ ./p1
0
1
2
3
4
5
[ghigo@therra tmp]$
Ma questo risolve solo uno dei tuoi problemi, la condivisione della stessa
variabile in memoroia. In realta' ce ne sono molti più subdoli del tipo:
1) siamo sicuri che tutte le funzioni siano thread-safe ?
2) Il tuo codice non è corretto ( cosi come è ) infatti c'è la possibilita
di avere un output del tipo ( come mi è capitato )
[ghigo@therra tmp]$ ./p1
0
1
2
0
4
5
Questo perchè i tread sono stati eseguiti cosi:
    thread1                            thread2                      i
1   cout << i << endl;                                              0
2                                      cout << i << endl;           0
3                                      i ++;                        1
4                                      cout << i << endl;           1
5                                      i ++;                        2
6                                      cout << i << endl;           2
7                                      i ++;                        3
8                                      
9   i ++;                                                           4
10  cout << i << endl;                                              4
11  i ++;                                                           5
12  cout << i << endl;                                              5
13  i ++;                                                           6
Il fatto che poi la scrittura sollo stream non sia stata "sincrona" ha fatto
si che la riga 1 è stata valutata per prima, ma il suo output è apparso
dopo, da cui la sequenza 0120456. Ma poteva anche comparire 0012456
Per ottenere quello che vuoi devi usare *anche* qualche maccanismo di
sincronizzazione del tipo mutex/ipc od altro...

Grazie per l'aiuto :)
In effetti ho formalizzato male il problema.
In pratica quello che devo fare e' gestire un timestamp generale su un
server.
Una serie di processi figli vengono generati per gestire degli upload
simultanei da parte di piu' client. Lo scopo del timestamp generale e'
di temporizzare gli upload con una partenza differita di 5 secondi.
La soluzione qui sopra prevede l'utilizzo di threads, ma io avrei
bisogno di mantenere la struttura a processi.
Sapete dirmi per favore se c'e' un modo per far condividere la
variabile del timestamp a tutti i processi? Mi hanno accennato a "IPC
Posix" su it.comp.lang.c++, dicendomi che e' una prerogativa del
sistema operativo, piu' che del linguaggio c++

 sistema operativo, piu' che del linguaggio c++
In effetti, Unix propone un kit chiamato IPC. Parte del kit sono i semafori,
le code messaggi e i segmenti di memoria condivisa. Con un segmento condiviso,
creare una variable "read-only" messa a giorno da un solo processo e` un gioco
da ragazzi...
Bisogna prima creare una chiave unica per la macchina (basta usare un file
comune per avere una chiave unica e "privata"). Usando la chiave si puo`
creare un segmento di memoria a cui altri processi possono attaccarsi in
modo di sola lettura. A questo punto basta creare un puntatore e inizializzarlo
all'indirizzo virtuale del segmento per condividere la stessa variabile. Dove
cominciano i problemi e` quando la variabile puo' essere sovrascritta da
piu` processi: nel caso, bisogna sincronizzarli.
Ti suggerisco il secondo volume dello Stevens "UNIX network programming". Una
bibbia per l'argomento.
Ciao,
-- 
       Roberto Divia`              Love at first sight is one of the greatest
Dep:PH Bat:53 Mailbox:C02110      labour-saving devices the world has ever seen
Route de Meyrin 385               ---------------------------------------------
Case Postale                                Phone:  
+41-22-767-4994
CH-1211 Geneve 23 CERN                      Fax:    
+41-22-767-9585
Switzerland                                 E-Mail: 
Robert...@cern.ch

Suggerimenti utilissimi, ho risolto il problema. Grazie Roberto!
Non avendo a disposizione il testo dello Stevens, ho usato "Guida alla
programmazione in linux", reperibile in rete all'indirizzo
http://gapil.firenze.linux.it
E' molto chiaro, e corredato di codice sorgente ben commentato.
Ciao!