#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;
  while(1) {
    r1=pick(); r2=pick();
    sleep(pick2());
    pthread_mutex_lock(&resource[r1]);
    res_str[r1]='1';
    while(pthread_mutex_trylock(&resource[r2]))  // om redan är låst, slumpa och prova en annan. Se mer beskrivning längst ner.
    {
        r2=pick();
    }
    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();
    sleep(pick2());
    pthread_mutex_lock(&resource[r1]);
    res_str[r1]='2';
     while(pthread_mutex_trylock(&resource[r2]))  // om redan är låst, slumpa och prova en annan. Se mer beskrivning längst ner.
    {
        r2=pick();
    }

    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++<60)
  {
    sleep(1);
    printf("%2d: %s\n", i, res_str);
  }
}
/*Lösning

Första lösning:
Trådarna låser en slumpvald mutex.
Problemet uppstår om de först låser varsin mutex och sedan försöker de låsa den andra trådens
mutex som redan är låst. Då uppstår cirkulär väntan som leder till deadlock.
En lösning skulle kunna vara att när båda har låst sin mutex och ska försöka låsa sin andra att
man testar ifall denna mutex är låst. Isåfall slumpar man om vilken mutex man ska låsa och man kommer
då komma ur deadlocken efter x antal försök. Eftersom den slumpar mellan 5 resurser att låsa går detta
fort. Man kan dock argumentera om denna lösning är optimal då oftast när man vill låsa en mutex till en
resurs vill man just ha denna resurs och inte en annan. Men då programmet går ut på att slumpa så spelar
detta ingen större roll.


Andra lösning: (se uppg3.2.c)
En bättre lösning. Tog ett litet tag att inse att ett av problemen med att välja resurs slumpmässigt
var att en tråd kunde försöka låsa en mutex den redan hade och kom därför in i ett deadlock.
Detta löstes med en if sats som kollade om de slumpmässiga talen r1 och r2 i tråden var samma och isåfall slumpa om r2
tills den var skild från r1.
Dock kvarstår problemet att trådarna kan fastna i deadlock om båda trådarna låst en mutex och sedan vill
försöka låsa den andra trådens mutex som redan är låst. Detta löstes genom prioritet.
Ena tråden ändrades till om mutexen inte kunde låsas så skulle den låsa upp den mutexen den hade i innehav
och vänta lite till att försöka låsa om allt igen.

*/

