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.