miércoles, 14 de septiembre de 2011

PRIMERA PRESENTACIÓN PRÁCTICA

Hola Mundo!!

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 productor
A) 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 :)


Códigos:

Ejecuciones:

viernes, 9 de septiembre de 2011

Primera presentación teórica


LOCKS (code)
Lock::Lock(const char* debugName) {
  name = debugName;
  s = new Semaphore(name,1);
  locked = true;
  owner = NULL;
}

Lock::~Lock() {
  delete s;
  delete owner;
}

void Lock::Acquire() {
  s->P();
  locked = true;
  owner = currentThread;
}

bool Lock::isHeldByCurrentThread() {
  return(owner == currentThread);
}

void Lock::Release() {
  if(locked && isHeldByCurrentThread()) {
    locked = false;
    owner = NULL;
    s->V();
  }
}
CONDITIONAL VARIABLES (code)
Condition::Condition(const char* debugName, Lock* conditionLock) {
  name = debugName;
  l = conditionLock;
  queue = new List;
}

Condition::~Condition() {
  delete l;
  delete queue;
}

void Condition::Wait() {
  Semaphore *temp;
  
  if(l->isHeldByCurrentThread()) {
    temp = new Semaphore("condition", 0);
    queue->Append(temp);
    l->Release();
    temp->P();
    l->Acquire();
    delete temp;
  }
}

void Condition::Signal() {
  Semaphore *temp;
  
  if(l->isHeldByCurrentThread()) {
    if(!queue->IsEmpty()) {
      temp = queue->Remove();
      temp->V();
    }
  }
}

void Condition::Broadcast() {
  while(!queue->IsEmpty()) {
    Signal();
  }
}