ALP - Aquileia Linux Project

Gruppo Utenti GNU/Linux – Free Software Bassa Friulana
Oggi è 22/07/2017, 20:33

Tutti gli orari sono UTC




Apri un nuovo argomento Rispondi all’argomento  [ 3 messaggi ] 
Autore Messaggio
MessaggioInviato: 06/07/2006, 17:47 
Non connesso
pinguino_crestato
pinguino_crestato

Iscritto il: 28/06/2006, 17:04
Messaggi: 45
Salve ragazzi! Avevo già postato un errore precedente, adesso sono andato molto più avanti ma mi sono bloccato su alcuni problemi.
Sto implementando un programmino didattico: sarebbe una emulazione del gioco di space invaders (ma 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

_________________
Linux Slackware 10.2 - Kernel 2.6


Top
 Profilo  
 
 Oggetto del messaggio:
MessaggioInviato: 12/07/2006, 16:16 
Non connesso
pinguino_crestato
pinguino_crestato

Iscritto il: 28/06/2006, 17:04
Messaggi: 45
Ho modificato il mio programma e ho corretto diversi errori ma il deadlock rimane..Il fatto è che il deadlock avviene solo in certe distribuzioni linux (slackware, ubuntu..) mentre in altre no (ad esempio mandriva...). Come mai??

_________________
Linux Slackware 10.2 - Kernel 2.6


Top
 Profilo  
 
 Oggetto del messaggio:
MessaggioInviato: 15/07/2006, 8:56 
Non connesso
pinguino_crestato
pinguino_crestato

Iscritto il: 28/06/2006, 17:04
Messaggi: 45
Ho corretto il progetto eliminando 2 mutex (avevo una gestione troppo appesantita che portava ad un deadlock) ed inoltre c'era anche un'errore di inizializzazione del generatore di numeri pseudo-casuali (avevo inizializzato srand() all'interno di una funzione mentre è buona norma inizializzarlo nel main ).
Grazie a chiunque abbia dato un'occhiata al codice! :ciauz:

_________________
Linux Slackware 10.2 - Kernel 2.6


Top
 Profilo  
 
Visualizza ultimi messaggi:  Ordina per  
Apri un nuovo argomento Rispondi all’argomento  [ 3 messaggi ] 

Tutti gli orari sono UTC


Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite


Non puoi aprire nuovi argomenti
Non puoi rispondere negli argomenti
Non puoi modificare i tuoi messaggi
Non puoi cancellare i tuoi messaggi
Non puoi inviare allegati

Cerca per:
Vai a:  
cron
Powered by phpBB® Forum Software © phpBB Group
Traduzione Italiana phpBBItalia.net basata su phpBB.it 2010
[ Time : 0.138s | 15 Queries | GZIP : Off ]