#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();
    sleep(pick2());
    test=pthread_mutex_trylock(&resource[r1]);
    //jag ändrade locksen till trylocks, så om trylocksen 
    //failar, dvs test != 0 så returnerar funktionen utan att 
    //göra någonting, så nu får jag inga deadlocks.
    if(test==0) res_str[r1]='1'; 
    //if satserna är egentligen onödiga då koden enbart 
    //fortsätter om mutexen ej är låst men jag gör det ändå 
    //för säkerhets skull
    test=pthread_mutex_trylock(&resource[r2]); //den del av problemet som en trylock löser är det faktum att en vanlig mutex_lock blockerar om locken inte fungerar medan en trylock omedelbart returnerar utan att låsa eller låsa upp
    if(test==0) res_str[r2]='1'; //vilket i vårat fall möjliggör slumpning av en annan resurs eller så att den andra tråden hinner låsa upp resursen för en till trylock nästa cykel.
    sleep(pick2());
    test=pthread_mutex_unlock(&resource[r1]);
    if(test==0)res_str[r1]='0';
    test=pthread_mutex_unlock(&resource[r2]);
    if(test==0)res_str[r2]='0';
  }
}

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

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);
  }
}
