Risultati da 1 a 2 di 2

Discussione: [C]linux: programma didattico comunicazione tra thread vers2

  1. #1
    New Member
    Data Registrazione
    03-09-2004
    Messaggi
    25

    [C]linux: programma didattico comunicazione tra thread vers2

    Salve ragazzi!
    Sto implementando un programmino didattico: sarebbe una emulazione del gioco di spaceinvaders (molto grezzo!),con grafica scarna.
    Il programma è quasi analogo al classico problema dei "produttori-consumatori": creo dei processi con relativi thread, che accedono ad un buffer condiviso (protetto da semafori), basandomi sulle librerie lpthread e lncurses.
    Il problema in cui mi sono impantanato adesso è relativo forse alla sincronizzazione che non funziona: gli alieni ad un certo punto si bloccano e le bombe che lancia la mia nave con il tasto INVIO non capisco come mai non vengono bloccate (homesso un controllo per fare sparare due bombe per volta ma non lo rispetta). Non capisco se il problema sono i semafori!
    Qualcuno può darmi una mano? Vi allego il codice:
    Codice:
    /*
    Autori: Carlo Buttu, Giovanni Bussu.
    Versione Beta 0.1
    Codice rilasciato su licenza GPL ( http://www.gnu.org/licenses/gpl-howto.html).
    */
    
    #include <stdio.h>
    #include <curses.h>
    #include <time.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <pthread.h>
    #include <semaphore.h>
    
    #define NUM_MAX_RIGHE 5
    #define SINISTRA 68
    #define DESTRA 67
    #define N_INIZIALE_ALIENI 10
    #define SPAZIO 2
    #define SPAZIO_RIGHE 1
    #define PASSO_X 2
    #define PASSO_Y 1
    #define MAX_BOMBE_NAVE 2
    #define MAX_BOMBE_ALIENO N_INIZIALE_ALIENI * 2
    #define DIM_BUFFER N_INIZIALE_ALIENI
    
    
    struct pos {
    char *c;
    int x;
    int y;
    int xPrec;
    int yPrec;
    int index;
    int id;
    };
    
    struct pos alieni[N_INIZIALE_ALIENI];
    struct pos info_nave;
    struct pos bombe_nave[MAX_BOMBE_NAVE];
    struct pos bombe_alieno[MAX_BOMBE_ALIENO];
    struct pos *info_elementi[DIM_BUFFER];
    
    void *alieno(void *);
    void *nave(void *);
    void *controllo(void *);
    void *sparaBomba(void *);
    void bomba(struct pos, struct pos *);
    
    pthread_t array_alieni[N_INIZIALE_ALIENI];
    pthread_t threadNave;
    pthread_t bombaNave[MAX_BOMBE_NAVE];
    pthread_t bombaAlieno[MAX_BOMBE_ALIENO];
    
    pthread_mutex_t semaforo = PTHREAD_MUTEX_INITIALIZER;
    pthread_mutex_t mutexBombeAlieni = PTHREAD_MUTEX_INITIALIZER;
    pthread_mutex_t mutexBombeNave = PTHREAD_MUTEX_INITIALIZER;
    pthread_mutex_t mutexAlieni = PTHREAD_MUTEX_INITIALIZER;
    pthread_mutex_t mutexNave = PTHREAD_MUTEX_INITIALIZER;
    
    sem_t vuoto, pieno;
    int dimAlieni, bufferScrittura, bufferLettura, nBombeNaveResidue, nBombeAlienoResidue, posDisponibileAlieno, posDisponibileNave;
    
    int main() {
    int i = 0, j = 1, k, nAlieniRiga;
    initscr();
    noecho();
    curs_set(0);
    bufferScrittura = 0;
    bufferLettura = 0;
    posDisponibileAlieno = 0;
    posDisponibileNave = 0;
    nBombeNaveResidue = MAX_BOMBE_NAVE;
    nBombeAlienoResidue = MAX_BOMBE_ALIENO;
    dimAlieni = 1;
    nAlieniRiga = COLS / (dimAlieni + SPAZIO);
    sem_init(&vuoto, 0, DIM_BUFFER);
    sem_init(&pieno, 0, 0);
    
    for (k = 0; k < N_INIZIALE_ALIENI; k++){
    	i = k % nAlieniRiga;
    	j =  (k / nAlieniRiga) + 1;
    	
    	alieni[k].x = i * (SPAZIO + 1);
    	alieni[k].y =  j * (SPAZIO_RIGHE + 1);
    	alieni[k].c = "#";
    	alieni[k].index = k;
    	pthread_create(&array_alieni[k], NULL, &alieno, &alieni[k]);
    }
    
    pthread_create(&threadNave, NULL, &nave, NULL);
    controllo(NULL);
    getchar();
    endwin();
    exit(0);
    }
    
    void *nave(void *args)
    {
    struct pos pos_nave;
    struct pos pos_bomba;
    pos_nave.c = "^";
    pos_nave.x = COLS / 2;
    pos_nave.yPrec = pos_nave.y = LINES - 1;
    pos_nave.index = N_INIZIALE_ALIENI; //per ora è inutile...
    sem_wait(&vuoto); //Segnala che è stata scritta un altra posizione nel buffer
    pthread_mutex_lock(&semaforo); //equivale ad una wait su valore 1
    info_elementi[bufferScrittura] = &pos_nave;
    bufferScrittura = (bufferScrittura + 1) % DIM_BUFFER;
    info_nave = pos_nave;
    pthread_mutex_unlock(&semaforo);
    sem_post(&pieno); //Segnala che c'è una posizione in più da leggere nel buffer
    while(1)
    	{
    	pos_nave.xPrec = pos_nave.x;
    	char c;
    	switch(c = getch())
    		{
    		case SINISTRA: if(pos_nave.x > 1) pos_nave.x -= 1;
    		break;
    		case DESTRA: if(pos_nave.x < COLS - 1) pos_nave.x += 1;
    		break;
    		case ' ':
    			pos_bomba.x = pos_bomba.xPrec = pos_nave.x;
    			pos_bomba.y = LINES - 2;
    			pos_bomba.c = "o";
    			pthread_mutex_lock(&mutexBombeNave);
    			if(nBombeNaveResidue > 0)
    				{
    				pthread_mutex_lock(&mutexNave);
    				pthread_create(&bombaNave[posDisponibileNave], NULL, &sparaBomba, &pos_bomba);
    				pthread_mutex_unlock(&mutexNave);
    				}
    			pthread_mutex_unlock(&mutexBombeNave);
    		}
    	if (c == DESTRA || c == SINISTRA)
    		{
    		sem_wait(&vuoto); //Segnala che è stata scritta un altra posizione nel buffer
    		pthread_mutex_lock(&semaforo); //equivale ad una wait su valore 1
    		info_elementi[bufferScrittura] = &pos_nave;
    		bufferScrittura = (bufferScrittura + 1) % DIM_BUFFER;
    		info_nave = pos_nave;
    		pthread_mutex_unlock(&semaforo);
    		sem_post(&pieno); //Segnala che c'è una posizione in più da leggere nel buffer
    		}
    	}
    }
    
    void *alieno(void *args)
    {
    struct pos pos_alieno = *(struct pos*) args;
    pos_alieno.id = pthread_self();
    int dir = 1, dx, dy;
    srand((int) pos_alieno.id);
    while(1)
    	{
    	pos_alieno.yPrec = pos_alieno.y;
    	pos_alieno.xPrec = pos_alieno.x;
    	dx = PASSO_X * dir;
    	dy = 0;
    	if (pos_alieno.x + dx >= COLS -1 || pos_alieno.x + dx <= 0)
    		{
    		if(dir > 0)
    			pos_alieno.x = COLS - 1;
    		else
    			pos_alieno.x = 0;
    		dir = -dir;
    		dx = PASSO_X * dir;
    		dy = PASSO_Y;
    		}
    	pos_alieno.x += dx;
    	pos_alieno.y += dy;
    	sem_wait(&vuoto); //Segnala che è stata scritta un altra posizione nel buffer
    	pthread_mutex_lock(&semaforo); //equivale ad una wait su valore 1
    	info_elementi[bufferScrittura] = &pos_alieno;
    	bufferScrittura = (bufferScrittura + 1) % DIM_BUFFER;
    	alieni[pos_alieno.index] = pos_alieno;
    	pthread_mutex_unlock(&semaforo);
    	sem_post(&pieno); //Segnala che c'è una posizione in più da leggere nel buffer
    	int t = clock();
    	if((rand() % 100) >= 65 - 1) // 1 qui equivale al livello....da aggiornare!
    	{
    		struct pos pos_bomba;
    		pos_bomba.x = pos_bomba.xPrec = pos_alieno.x;
    		pos_bomba.y = pos_alieno.y + 1;
    		pos_bomba.c = "!";
    		pthread_mutex_lock(&mutexBombeAlieni);
    		if(nBombeAlienoResidue > 0)
    			{
    			pthread_mutex_lock(&mutexAlieni);
    			pthread_create(&bombaAlieno[posDisponibileAlieno], NULL, &sparaBomba, &pos_bomba);
    			pthread_mutex_unlock(&mutexAlieni);
    			}
    		pthread_mutex_unlock(&mutexBombeAlieni);
    	}
    	t = 1 - clock() - t;
    	sleep((int)t);
    	}
    }
     
    void *controllo(void *args)
    {
    struct pos valore_letto;
    int index;
    do {
    	sem_wait(&pieno); //Segnala che è stata letta una posizione dal buffer
    	pthread_mutex_lock(&semaforo);
    	valore_letto = *info_elementi[bufferLettura];
    	bufferLettura = (bufferLettura + 1) % DIM_BUFFER;
    	pthread_mutex_unlock(&semaforo);
    	sem_post(&vuoto);
    	move(valore_letto.yPrec, valore_letto.xPrec);
    	printw(" ");
    	move(valore_letto.y, valore_letto.x);
    	printw("%s",valore_letto.c);
    	move(0,0);
    	printw("Bombe nave %d",nBombeNaveResidue);
    	//move(1,0);
    	//printw("Bombe alieno %d",nBombeAlienoResidue);
    	refresh();
    	}
    while (true);
    }
    
    void *sparaBomba(void *args)
    {
    struct pos pos_bomba = *(struct pos*) args;
    struct pos *posizione;
    pos_bomba.id = pthread_self();
    if(pos_bomba.c == "!") // è un alieno?
    	{
    	pthread_mutex_lock(&mutexBombeAlieni);
    	if(nBombeAlienoResidue > 0)
    		{
    		nBombeAlienoResidue--;
    		pos_bomba.index = posDisponibileAlieno; // per ora è inutile...
    		posDisponibileAlieno = (posDisponibileAlieno + 1) % MAX_BOMBE_ALIENO;
    		posizione = &bombe_alieno[posDisponibileAlieno];
    		pthread_mutex_unlock(&mutexBombeAlieni);
    		bomba(pos_bomba, posizione);
    		pthread_mutex_lock(&mutexBombeAlieni);
    		nBombeAlienoResidue++;
    		posDisponibileAlieno = (posDisponibileAlieno - 1) % MAX_BOMBE_ALIENO;
    		}
    	pthread_mutex_unlock(&mutexBombeAlieni);
    	}
    	else
    		if(pos_bomba.c == "o") //è una nave?
    			{
    			pthread_mutex_lock(&mutexBombeNave);
    			if(nBombeNaveResidue > 0)
    				{
    				nBombeNaveResidue--;
    				pos_bomba.index = posDisponibileNave; //per ora è inutile...
    				posDisponibileNave = (posDisponibileNave + 1) % MAX_BOMBE_NAVE;
    				posizione = &bombe_nave[posDisponibileNave];
    				pthread_mutex_unlock(&mutexBombeNave);
    				bomba(pos_bomba, posizione);
    				pthread_mutex_lock(&mutexBombeNave);
    				nBombeNaveResidue++;
    				posDisponibileNave = (posDisponibileNave - 1) % MAX_BOMBE_NAVE;
    				}
    			pthread_mutex_unlock(&mutexBombeNave);
    			}
    }
    
    void bomba(struct pos pos_bomba, struct pos *posizione)
    {
    int limite = (pos_bomba.c == "!") ? LINES - 1 : 0;
    int dir = (pos_bomba.c == "!") ? 1 : -1;
    	sem_wait(&vuoto); //Segnala che è stata scritta un altra posizione nel buffer
    	pthread_mutex_lock(&semaforo); //equivale ad una wait su valore 1
    	info_elementi[bufferScrittura] = &pos_bomba;
    	bufferScrittura = (bufferScrittura + 1) % DIM_BUFFER;
    	*posizione = pos_bomba;
    	pthread_mutex_unlock(&semaforo);
    	sem_post(&pieno); //Segnala che c'è una posizione in più da leggere nel buffer
    while(pos_bomba.y != limite)
    	{
    	usleep(100000);
    	pos_bomba.yPrec = pos_bomba.y;
    	pos_bomba.y += dir;
    	sem_wait(&vuoto); //Segnala che è stata scritta un altra posizione nel buffer
    	pthread_mutex_lock(&semaforo); //equivale ad una wait su valore 1
    	info_elementi[bufferScrittura] = &pos_bomba;
    	bufferScrittura = (bufferScrittura + 1) % DIM_BUFFER;
    	*posizione = pos_bomba;
    	pthread_mutex_unlock(&semaforo);
    	sem_post(&pieno); //Segnala che c'è una posizione in più da leggere nel buffer
    	}
    pos_bomba.c = " ";
    sem_wait(&vuoto); //Segnala che è stata scritta un altra posizione nel buffer
    pthread_mutex_lock(&semaforo); //equivale ad una wait su valore 1
    info_elementi[bufferScrittura] = &pos_bomba;
    bufferScrittura = (bufferScrittura + 1) % DIM_BUFFER;
    *posizione = pos_bomba;
    pthread_mutex_unlock(&semaforo);
    sem_post(&pieno); //Segnala che c'è una posizione in più da leggere nel buffer
    }
    P.S. Compilare con le opzioni -lpthread & -lncurses, es:
    gcc -o alieni alienThread.c -lncurses -lpthread

  2. #2
    SWZone Staff - Moderatrice
    La Segretaria
    Ogni Club ha la segretaria
    che merita

    Member of Swzone Ferrari club
    L'avatar di frabi
    Data Registrazione
    27-12-2002
    Località
    Cagliari
    Messaggi
    31.573
    caralu, il tuo thread esiste gi&#224; nella sezione Linux, quindi questo si chiude.
    Chi ha linux, o chi &#232; interessato legge quella sezione.

Segnalibri

Permessi di Scrittura

  • Tu non puoi inviare nuove discussioni
  • Tu non puoi inviare risposte
  • Tu non puoi inviare allegati
  • Tu non puoi modificare i tuoi messaggi
  •