]> git.llucax.com Git - z.facultad/75.74/practicos.git/blob - practicas/practica2/P02e2221.cpp
Ya estamos fragmentando! (falta testing intensivo pero parece andar)
[z.facultad/75.74/practicos.git] / practicas / practica2 / P02e2221.cpp
1 /**
2  * Leandro Lucarella (77891)
3  *
4  * Ejercicio 2.2.2. Implementa productor-consumidor con colas de mensajes, con 3
5  * productores que producen 1/3 cada uno y 2 consumidores que consumen todo.
6  */
7
8 #include <iostream>
9 #include <cstdlib>
10 #include <unistd.h>
11 #include <fcntl.h>
12 #include <sys/types.h>
13 #include <sys/ipc.h>
14 #include <sys/msg.h>
15
16 using std::cerr;
17 using std::cout;
18 using std::endl;
19
20 /// Clave de nuestro segmento shm y semaforo
21 #define MSG_KEY 0x77891226
22
23 void msgbuf_init(msgbuf* m, char val, int type)
24 {
25     m->mtype = type;
26     m->mtext[0] = val;
27 }
28
29 void msgbuf_set_val(msgbuf* m, char val)
30 {
31     m->mtext[0] = val;
32 }
33
34 void msgbuf_set_type(msgbuf* m, char type)
35 {
36     m->mtype = type;
37 }
38
39 char msgbuf_get(msgbuf* m)
40 {
41     return m->mtext[0];
42 }
43
44 /// Nombres de los procesos
45 enum proc_t { PRODUCTOR1, PRODUCTOR2, PRODUCTOR3, CONSUMIDOR1, CONSUMIDOR2 };
46
47 /// Nombres del typo de mensaje según la parte a producir (se produce la misma
48 /// parte 2 veces, una para cada consumidor
49 enum msg_t { PARTE11 = 1, PARTE21, PARTE31, PARTE12, PARTE22, PARTE32 };
50
51 msg_t msg_types[3][2] =
52 {
53     { PARTE11, PARTE12 },
54     { PARTE21, PARTE22 },
55     { PARTE31, PARTE32 }
56 };
57
58 #define TEST(v) do { if ((v) == -1) { perror("P02e2221"); exit(200); } } while (0)
59
60 void producir(int que_id, int parte)
61 {
62     char val = rand();
63     msgbuf msg;
64     msgbuf_init(&msg, val, msg_types[parte][0]);
65     TEST(msgsnd(que_id, &msg, 1, 0));
66     //sched_yield();
67     msgbuf_set_type(&msg, msg_types[parte][1]);
68     TEST(msgsnd(que_id, &msg, 1, 0));
69     //sched_yield();
70     cout << "Producida parte " << parte  << ": " << (int)val << endl;
71     sched_yield();
72 }
73
74 void consumir(int que_id, int consumidor)
75 {
76     int completo[3];
77     msgbuf msg;
78     TEST(msgrcv(que_id, &msg, 1, msg_types[0][consumidor], 0));
79     //sched_yield();
80     completo[0] = msg.mtext[0];
81     TEST(msgrcv(que_id, &msg, 1, msg_types[1][consumidor], 0));
82     //sched_yield();
83     completo[1] = msg.mtext[0];
84     TEST(msgrcv(que_id, &msg, 1, msg_types[2][consumidor], 0));
85     //sched_yield();
86     completo[2] = msg.mtext[0];
87     cout << "Consumidor " << consumidor << " consumió: " << completo[0] << ","
88         << completo[1] << "," << completo[2] << endl;
89     sched_yield();
90 }
91
92 int main(int argc, char *argv[])
93 {
94     if (argc < 2)
95     {
96         cerr << "Faltan parametros: " << argv[0] << " N [max_iter]\n";
97         return 1;
98     }
99     proc_t proc = (proc_t) atoi(argv[1]);
100
101     // Cola
102     int que_id;
103     do
104     {
105         // crea solo si es el proceso 0
106         que_id = msgget(MSG_KEY, (proc ? 0 : IPC_CREAT) | 0666);
107     }
108     while (proc != PRODUCTOR1 && que_id == -1);
109
110     // Maxima cantidad de iteraciones (puede venir por parametro)
111     int max_iter = 10;
112     if (argc > 2)
113         max_iter = atoi(argv[2]);
114
115     srand(getpid());
116
117     // Loop principal
118     for (int i = 0; i < max_iter; ++i)
119     {
120         if (proc < 3) // productor
121             producir(que_id, proc);
122         else
123             consumir(que_id, proc-3);
124     }
125
126     return 0;
127 }
128
129 // vim: set et sw=4 sts=4 :