#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>

pthread_mutex_t resource[5];
char res_str[] = "00000";

int pick(){return rand()%5;}
int pick2(){return rand()%2+1;}

void* t1 (void * p) {
  int r1, r2, test;
  while(1) {
    r1=pick(); r2=pick();
    while(r1 == r2){
      r1=pick();
    }
    sleep(pick2());
    pthread_mutex_lock(&resource[r1]);
    res_str[r1]='1';
    while(pthread_mutex_trylock(&resource[r2]) != 0){
    pthread_mutex_unlock(&resource[r1]);
    sleep(1);
    pthread_mutex_lock(&resource[r1]);
    }
    res_str[r2]='1';
    sleep(pick2());
    res_str[r1]='0';
    res_str[r2]='0';
    pthread_mutex_unlock(&resource[r1]);
    pthread_mutex_unlock(&resource[r2]);
  }
}

void* t2 (void * p) {
  int r1, r2;
  while(1) {
    r1=pick(); r2=pick();
    while(r1 == r2){
      r1=pick();
    }
    sleep(pick2());
    pthread_mutex_lock(&resource[r1]);
    res_str[r1]='2';
    while(pthread_mutex_trylock(&resource[r2]) != 0){
    pthread_mutex_unlock(&resource[r1]);
    sleep(1);
    pthread_mutex_lock(&resource[r1]);
    }
    res_str[r2]='2';
    sleep(pick2());
    res_str[r1]='0';
    res_str[r2]='0';
    pthread_mutex_unlock(&resource[r1]);
    pthread_mutex_unlock(&resource[r2]);
  }
}

main() {
  int i=0,n;
  pthread_t id1, id2;
  pthread_create(&id1,NULL,&t1,NULL);
  pthread_create(&id2,NULL,&t2,NULL);
  while(i++<30)
  {
    sleep(1);
    printf("%2d: %s\n", i, res_str);
  }
}

/* 
Så som jag ser det fanns det två anledningar till att det skulle kunna bli deadlock.
Den första är om r1 och r2 blir samma tal i en av trådarna. 
Eftersom processen då skulle försöka låsa t.ex res_str[2] två ggr efter varandra skulle den andra mutex lock 
vänta på att res_str[2] skulle bli upplåst villket den inte skulle bli.
Lösning: se till att om r1 & r2 är samma slumpa om dom tills de inte är så längre.

Andra scenariot är om det skulle ske en cirkulär väntan mellan processena. Detta skulle kunna se ut såhär:
tråd 1 lås: 	      res_str[1]
context switch
tråd 2 lås: 	      res_str[2]
context switch
tråd 1 försöker låsa: res_str[2]
context switch 
tråd 2 försöker låsa: res_str[1]
deadlock

lösning: använd trylock i en whileloop som låser upp den tidigare låsta mutexen och väntar på att båda mutexarna ska vara fria.

*/
