1. Para la primera parte realizamos un pequeño código que prueba la manera como funcionan los candados.
Lock *L = new Lock("testLock");
void printFunc(void* name) {
int i = 0;
L->Acquire();
for(i; i<=5; i++) {
printf("[%s] Testing Locks - No. [%d]\n", (char *)name, i);
}
L->Release();
}
void ThreadTest() {
DEBUG('t', "Testing the lock and another things");
printf ("TESTING:\n\n");
const char* name;
Thread* t1 = new Thread("Cecy");
name = t1->getName();
t1->Fork(printFunc, (void *)name);
Thread* t2 = new Thread("Roberto");
name = t2->getName();
t2->Fork(printFunc, (void *)name);
Thread* t3 = new Thread("Juan");
name = t3->getName();
t3->Fork(printFunc, (void *)name);
}
EJECUCIÓN
2. Para nuestra primera presentación práctica decimos dar solución al problema de productorA) Solución usando candados:
Lock *L = new Lock("testLock");
int buffer = 0;
void bufferState() {
printf("Buffer = [ %d ]\n", buffer);
}
void producer(void* name) {
while(true) {
L->Acquire();
printf("[%s] producing data\n", (char *)name);
buffer++;
bufferState();
L->Release();
currentThread->Yield();
}
}
void consumer(void* name) {
while(true) {
L->Acquire();
while(buffer == 0) {
L->Release();
currentThread->Yield();
}
printf("[%s] consuming data\n", (char *)name);
buffer--;
bufferState();
L->Release();
}
}
void ThreadTest() {
DEBUG('t', "Probando los candados y otras cosas");
printf ("Producer-Consumer:\n\n");
const char* name;
Thread* t1 = new Thread("Cecy");
name = t1->getName();
t1->Fork(producer, (void *)name);
Thread* t3 = new Thread("Juan");
name = t3->getName();
t3->Fork(producer, (void *)name);
Thread* t2 = new Thread("Roberto");
name = t2->getName();
t2->Fork(consumer, (void *)name);
}
EJECUCIÓN
B) Solución usando semáforos
Semaphore* s1 = new Semaphore("cecy", 1);
Semaphore* s2 = new Semaphore("robert", 0);
int buffer = 0;
void bufferState() {
printf("Buffer = [ %d ]\n", buffer);
}
void producer(void* name) {
while(true) {
s1->P();
printf("[%s] producing data [S]\n", (char *)name);
buffer++;
bufferState();
if(buffer == 1) {
s2->V();
}
s1->V();
currentThread->Yield();
}
}
void consumer(void* name) {
int temp;
s2->P();
while(true) {
s1->P();
printf("[%s] consuming data. [S]\n", (char *)name);
buffer--;
temp = buffer;
bufferState();
s1->V();
if(temp == 0){
s2->P();
}
}
}
void ThreadTest() {
DEBUG('t', "Probando los candados y otras cosas");
printf ("Productor-Consumidor con semaforos:\n\n");
const char* name;
Thread* t1 = new Thread("Cecy");
name = t1->getName();
t1->Fork(producer, (void *)name);
Thread* t2 = new Thread("Juan");
name = t2->getName();
t2->Fork(producer, (void *)name);
Thread* t3 = new Thread("Roberto");
name = t3->getName();
t3->Fork(consumer, (void *)name);
}
EJECUCIÓN
C) Solución usando Variables Condicionales
Lock* l1 = new Lock("l1");
Condition* c = new Condition("cecy", l1);
int buffer;
int limite = 10;
void bufferState() {
printf("Buffer = [ %d ]\n", buffer);
}
void anadir() {
l1->Acquire();
while(buffer == limite) {
c->Wait();
}
buffer++;
bufferState();
c->Signal();
l1->Release();
}
void extraer() {
l1->Acquire();
while(buffer == 0) {
c->Wait();
}
buffer--;
bufferState();
c->Signal();
l1->Release();
}
void producer(void* name) {
while(true) {
anadir();
printf("[%s] producing data [CV]\n", (char *)name);
}
}
void consumer(void* name) {
while(true) {
extraer();
printf("[%s] consuming data [CV]\n", (char *)name);
}
}
void ThreadTest() {
DEBUG('t', "Probando los candados y otras cosas");
printf ("Productor-Consumidor con variables de condicion:\n\n");
const char* name;
Thread* t1 = new Thread("Roberto");
name = t1->getName();
t1->Fork(producer, (void *)name);
Thread* t2 = new Thread("Juan");
name = t2->getName();
t2->Fork(producer, (void *)name);
Thread* t3 = new Thread("Cecy");
name = t3->getName();
t3->Fork(consumer, (void *)name);
}
EJECUCIÓN
REFERENCIAS: Nos basamos más que nada en los pseudocódigos vistos en las notas y en los libros de Stalling, Tanenbaum, y el de los dinosaurios :)



