ZSO – Pierwszy projekt Yuriego i mój w C/C++

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.
Ten wpis został opublikowany w kategorii PJWSTK, PJWSTK - ZSO. Dodaj zakładkę do bezpośredniego odnośnika.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *