Pierwszy projekt Yuri’ego:
/*
Zadanie 13. Problem orangutanów. Nad głębokim kanionem, gdzieś w Ameryce Południowej, rozpięta jest lina. Używają jej orangutany by przekroczyć kanion. Lina wytrzymuje ciężar pięciu małp a dwa orangutany nie mogą jednocześnie przechodzić po niej z przeciwnych stron kanionu. Po wejściu na linę nie można zawrócić z drogi. Każda małpa oczekująca na przejście musi kiedyś zostać obsłużona.
xubuntu: g++ o.cpp -pthread -std=c++0x -o zad01test
./zad01test
*/
#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include <tr1/random>
int iloscOrangutanow = 90;
// tylko jeden orangutan moze wchodzic/schodzic z liny w danym momencie, ale moze byc kilka naraz na linie
pthread_mutex_t mutexLicznikaMalpNaLinie = PTHREAD_MUTEX_INITIALIZER;
// wysylany kiedy orangutan schodzi z liny do orangutanow oczekujacych na miejsce na linie
pthread_cond_t sygnal = PTHREAD_COND_INITIALIZER;
// jak 0 orangutanow na linie to mozna zmienic kierunek
int iloscOrangutanowNaLinie = 0;
// kierunek z ktorego ida to: 'A' lub 'B'
char kierunekOrangutanowNaLinie = 'A';
int przeszlo = 0;
// generator liczb losowych uzywajac algotymu Mersenne Twister
std::tr1::mt19937 losowacz;
// losowany 'int' od 0 do 1, czyli 0 lub 1
std::tr1::uniform_int<int> losowyInt_od_0_do_1(0,1);
void *orangutan(void *id)
{
int idOrangutana = (int) id;
pthread_mutex_lock(&mutexLicznikaMalpNaLinie);
int kierunekWchodzacegoOrangutana;
if(losowyInt_od_0_do_1(losowacz) == 1)
{
kierunekWchodzacegoOrangutana = 'A';
}
else
{
kierunekWchodzacegoOrangutana = 'B';
}
while(iloscOrangutanowNaLinie == 5 || (iloscOrangutanowNaLinie > 0 && kierunekWchodzacegoOrangutana != kierunekOrangutanowNaLinie))
{
pthread_cond_wait(&sygnal, &mutexLicznikaMalpNaLinie);
}
if(kierunekWchodzacegoOrangutana != kierunekOrangutanowNaLinie)
{
kierunekOrangutanowNaLinie = kierunekWchodzacegoOrangutana;
printf("ZMIENIA SIE KIERUNEK ORANGUTANOW PRZECHODZACYCH PRZEZ LINE\n");
}
iloscOrangutanowNaLinie++;
printf("Orangutan %d: Wchodze %c, na linie: %d\n", idOrangutana, kierunekWchodzacegoOrangutana, iloscOrangutanowNaLinie);
pthread_mutex_unlock(&mutexLicznikaMalpNaLinie);
// czas przejscia przez line
usleep(100000);
pthread_mutex_lock(&mutexLicznikaMalpNaLinie);
iloscOrangutanowNaLinie--;
przeszlo++;
printf("Orangutan %d: Schodze %c, na linie: %d, przeszlo: %d\n", idOrangutana, kierunekWchodzacegoOrangutana, iloscOrangutanowNaLinie, przeszlo);
pthread_cond_broadcast(&sygnal);
pthread_mutex_unlock(&mutexLicznikaMalpNaLinie);
pthread_exit(NULL);
}
int main()
{
int idOrangutana=0;
pthread_t tablicaWatkowOrangutanow[iloscOrangutanow];
for(idOrangutana = 0; idOrangutana < iloscOrangutanow; idOrangutana++)
{
pthread_create(&tablicaWatkowOrangutanow[idOrangutana], NULL, orangutan, (void*) (idOrangutana+1));
}
for(idOrangutana = 0; idOrangutana < iloscOrangutanow; idOrangutana++)
{
pthread_join(tablicaWatkowOrangutanow[idOrangutana], NULL);
}
return EXIT_SUCCESS;
}
Tutaj moje rozwiązanie mojego zadania na 9/10, bo kanibal zabija kucharza exit(EXIT_SUCCESS);, a powinien wysłać mu sygnał po którym ten wykona pthread_kill:
#include <sys/time.h>
#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include <time.h>
#include <stdlib.h>
int ilosc_misjonarzy = 200;
int ilosc_kanibali = 20;
int kociol_ilosc_misjonarzy = 0;
int kociol_limit_misjonarzy = 10;
pthread_mutex_t mutex_1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex_2 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex_3 = PTHREAD_MUTEX_INITIALIZER;
/*pthread_mutex_t mutex_4 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex_5 = PTHREAD_MUTEX_INITIALIZER; // jedzenie*/
pthread_mutex_t mutex_6 = PTHREAD_MUTEX_INITIALIZER; // wchodzenie
pthread_cond_t signal_1 = PTHREAD_COND_INITIALIZER;
pthread_cond_t signal_2 = PTHREAD_COND_INITIALIZER;
/*pthread_cond_t signal_3 = PTHREAD_COND_INITIALIZER;
pthread_cond_t signal_4 = PTHREAD_COND_INITIALIZER;
p thread_cond_t signal_5 = PTHREAD_COND_INITIALIZER;*/
int kociolWejdz()
{
int ret = 0;
if(pthread_mutex_trylock(&mutex_6) == 0) // jesli odblokowane wchodzenie do gara
{
if(kociol_ilosc_misjonarzy < kociol_limit_misjonarzy)
{
kociol_ilosc_misjonarzy++;
ret = 1;
}
pthread_mutex_unlock(&mutex_6);
}
return ret;
}
int kociolWyjmij()
{
int ret;
if(kociol_ilosc_misjonarzy > 0)
{
kociol_ilosc_misjonarzy--;
ret = 1;
}
else
ret = 0;
return ret;
}
void* misjonarz()
{
pthread_mutex_lock(&mutex_1);
while (1)
{
pthread_cond_wait( &signal_1, &mutex_1 );
if(kociolWejdz() == 1)
{
// misjonarz ginie
break;
}
}
pthread_mutex_unlock(&mutex_1);
pthread_exit(NULL);
}
void* kucharz()
{
int czas_koniec_czekania;
pthread_mutex_lock(&mutex_6); // blokuje wchodzenie do gara
printf("Blokuje gar\n");
pthread_mutex_lock(&mutex_2);
while (1)
{
printf("Ide spac\n");
pthread_cond_wait( &signal_2, &mutex_2 ); // czeka na sygnal od kanibala
printf("Ktos mnie obudzil\n");
pthread_mutex_unlock(&mutex_6); // odblokowuje wchodzenie do gara
pthread_cond_broadcast(&signal_1);
czas_koniec_czekania = time(NULL) + 5;
printf("Czekam az misjonarze wskocza do gara do %d jest %d\n", czas_koniec_czekania, (int) time(NULL));
while(kociol_limit_misjonarzy != kociol_ilosc_misjonarzy && czas_koniec_czekania > time(NULL))
{
// czeka na napelnienie gara
// pthread_cond_broadcast(&signal_1); czy bez tego 'signal' pozostanie zapamietany po broadcast??
}
printf("Misjonarze wskoczyli, jest ich %d\n", kociol_ilosc_misjonarzy);
pthread_mutex_lock(&mutex_6); // blokuje wchodzenie do gara
printf("Blokuje gar\n");
pthread_cond_broadcast(&signal_2); // informuje kanibala, ze juz moze jesc
printf("Informuje kanibala o napelnieniu gara\n");
}
pthread_mutex_unlock(&mutex_2);
}
void* kanibal()
{
int ile_chce_zjesc;
int i;
while (1)
{
ile_chce_zjesc = (int)(rand() / (RAND_MAX + 1.0) * 10.0) + 1;
printf("Chce zjesc %d\n", ile_chce_zjesc);
pthread_mutex_lock(&mutex_3);
pthread_mutex_lock(&mutex_2);
printf("Przechodze do jedzenia\n");
if(kociol_ilosc_misjonarzy >= ile_chce_zjesc)
{
printf("Jest dosc w garze\n");
// tylko jeden kanibal moze jesc naraz,
// wiec nie ma obaw,
// ze misjonarze znikna z kotla w inny sposob,
// nie trzeba sprawdzac co zwraca kociolWyjmij()
for(i = 0; i < ile_chce_zjesc; i++)
{
kociolWyjmij();
}
}
else
{
printf("Nie ma dosc w garze\n");
pthread_cond_broadcast(&signal_2);
printf("Czekam na kucharza\n");
pthread_cond_wait( &signal_2, &mutex_2 );
printf("Doczekalem sie na kucharza\n");
while(ile_chce_zjesc > 0)
{
if(kociolWyjmij())
{
printf("!!!!!!!!!!!! Nie bylo dosc w garze, arg!\n");
// jesli udalo sie wyjac z kotla
// to znaczy, ze kucharz tam dolozyl misjonarza
ile_chce_zjesc--;
}
else
break;
}
if(ile_chce_zjesc > 0)
{
printf("!!!!!!!!!!!! Nie bylo dosc w garze, arg!\n");
// kanibal sie zdenerwowal, nie dostal w 5 sekund dosc misjonarzy
// zjedz kucharza
// koniec uczty
exit(EXIT_SUCCESS);
}
}
pthread_mutex_unlock(&mutex_2);
pthread_mutex_unlock(&mutex_3);
}
}
int main()
{
int i;
pthread_t kucharz_t;
pthread_t misjonarze_t[ilosc_misjonarzy];
pthread_t kanibale_t[ilosc_kanibali];
srand(time(NULL));
pthread_create(&kucharz_t,NULL,kucharz,NULL);
for(i = 0; i < ilosc_misjonarzy; i++)
{
pthread_create(&misjonarze_t[i],NULL,misjonarz,NULL);
}
for(i = 0; i < ilosc_kanibali; i++)
{
pthread_create(&kanibale_t[i],NULL,kanibal,NULL);
}
pthread_join(kucharz_t,NULL);
for(i = 0; i < ilosc_misjonarzy; i++)
{
pthread_join(misjonarze_t[i],NULL);
}
for(i = 0; i < ilosc_kanibali; i++)
{
pthread_join(kanibale_t[i],NULL);
}
return EXIT_SUCCESS;
}
Czekam jeszcze na kod od Justyny.