- using std::cerr;
- using std::cout;
-
- if (argc < 2)
- {
- cerr << "Faltan parametros: " << argv[0] << " (0|1) [max_iter]\n";
- return 1;
- }
- int proc = atoi(argv[1]);
-
- int shm_id = shmget(SHM_KEY, sizeof(Molinete), IPC_CREAT | 0666);
- if (shm_id == -1)
- {
- cerr << "Error al crea/obtener shared memory.\n";
- return 2;
- }
- Molinete* molinete = (Molinete*) shmat(shm_id, NULL, 0);
- if (molinete == (Molinete*) -1)
- {
- cerr << "Error al attachear shared memory.\n";
- return 3;
- }
-
- cout << "Shared memory id = " << shm_id << "\n";
-
- // Si somos el primer proceso inicializamos el molinete
- if (!proc) molinete_init(*molinete);
-
- // Maxima cantidad de iteraciones (puede venir por parametro)
- int max_iter = 100000;
- if (argc > 2)
- max_iter = atoi(argv[2]);
-
- // Loop principal
- for (int i = 0; i < max_iter; ++i)
- {
- bool dec = rand() % 2;
- int count;
- mutex_acquire(molinete->mutex, proc);
- if (dec && molinete->count) // Decremento sólo si no es 0
- count = --molinete->count;
- else
- count = ++molinete->count;
- mutex_release(molinete->mutex, proc);
- // Uso cout directamente porque es line-buffered, mientras que
- // no use threads no es problema el buffer de cout. Y de todas
- // formas pongo un flush (el endl es \n+flush) por las dudas.
- cout << "Proceso " << proc << ": molinete = " << count << std::endl;
- //sched_yield(); // Para ver como se entrelazan mejor
- }
-
- if (shmdt(molinete) == -1)
- {
- cerr << "Error al detachear shared memory.\n";
- return -1;
- }
-
- return 0;
+ using std::cerr;
+ using std::cout;
+
+ if (argc < 2)
+ {
+ cerr << "Faltan parametros: " << argv[0] << " (0|1) [max_iter]\n";
+ return 1;
+ }
+ int proc = atoi(argv[1]);
+
+ int shm_id;
+ do
+ {
+ shm_id = shmget(SHM_KEY, sizeof(Molinete),
+ (proc ? 0 : IPC_CREAT) | 0666); // crea solo si es el proceso 0
+ }
+ while (proc != 0 && shm_id == -1);
+ Molinete* molinete = (Molinete*) shmat(shm_id, NULL, 0);
+ if (molinete == (Molinete*) -1)
+ {
+ cerr << "Error al attachear shared memory.\n";
+ return 3;
+ }
+
+ // Si somos el primer proceso inicializamos el molinete
+ if (proc == 0) molinete_init(*molinete);
+
+ // Maxima cantidad de iteraciones (puede venir por parametro)
+ int max_iter = 100;
+ if (argc > 2)
+ max_iter = atoi(argv[2]);
+
+ srand(getpid());
+
+ // Loop principal
+ for (int i = 0; i < max_iter; ++i)
+ {
+ char sdec[] = "sale";
+ char sinc[] = "entra";
+ char* s;
+ bool dec = rand() % 2;
+ int count;
+ mutex_acquire(molinete->mutex, proc);
+ if (dec && molinete->count) // Decremento sólo si no es 0
+ {
+ s = sdec;
+ count = --molinete->count;
+ }
+ else
+ {
+ s = sinc;
+ count = ++molinete->count;
+ }
+ mutex_release(molinete->mutex, proc);
+ // Uso cout directamente porque es line-buffered, mientras que
+ // no use threads no es problema el buffer de cout. Y de todas
+ // formas pongo un flush (el endl es \n+flush) por las dudas.
+ cout << "Proceso " << proc << " (" << s << "): molinete = " << count
+ << std::endl;
+ sched_yield(); // Para ver como se entrelazan mejor
+ }
+
+ if (shmdt(molinete) == -1)
+ {
+ cerr << "Error al detachear shared memory.\n";
+ return -1;
+ }
+
+ return 0;