Visenitna konzolna aplikacija - C

poruka: 4
|
čitano: 1.518
|
moderatori: XXX-Man, vincimus
1
+/- sve poruke
ravni prikaz
starije poruke gore
16 godina
offline
Visenitna konzolna aplikacija - C

Pozdrav!

 

Radim program u cistom C-u, koristim pthread. Radi se o simulaciji raskrizja, gdje generiram promet u posebnoj niti (trafficGenerator). Postoji globalno polje intova u kojima cuvam broj vozila koj cekaju na prolaz kroz raskrizje, te stanja semafora za svaku cestu. Imam i drugu nit koja svakih 0.2 sekunde ispisuje u konzolu trenutno stanje u raskrizju. Ima jos toga, ali sam pojednostavio da ne trpam puno koda ovdje.

 

Sve je ok, niti rade fino, generira se promet i sve ok.

 

Ali problem je ovaj: kako napraviti izlazak iz programa? Ja imam int globalnu varijablu za stanje (_bProgramState), i sve niti ju ckeckiraju stalno. Ako je 1 ili 2, niti vrte svoju beskonacnu petlju, a prekidam izvrsavanje tih niti ako tu globalnu varijablu postavim na 0.

Kako to napraviti? Da li mogu imati jos jednu nit u kojoj stalno pozivam getch() i provjeravam ili nesto drugo? Brine me sto program ne smije cekati na input, nego treba prepoznati ako sam ja nesto stisnuo.

 

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <time.h>

//globalne varijable i parametri za stanje prometa
#define NUM_ROADS 4       //broj cesta

int maxVrijemeCekanja = 3000;//max vrijeme cekanja na novo vozilo u ms
int minVrijemeCekanja = 500;//min vrijeme cekanja na novo vozilo u ms

int vozilaNaCesti[NUM_ROADS] = {0,0,0,0};//vozila koja cekaju na prolaz raskrizjem
int semafor[NUM_ROADS] = {1,0,0,0};//stanja semafora na raskrizju (0-crveno, 1-zeleno)
int _bProgramState = 1;//0-zaustavljanje programa, 1-pause, 2-running


//funkcija za pauziranje - cekanje odredjenog vremena
void Sleep(int millis)
{
    clock_t last_check = clock() + millis;
    while(1)
    {
       if( clock() < last_check  )
          continue;
       break;
    }
}

//generiranje slucajnog broja izmedju zadanih granica
int RangedRandom( int range_min, int range_max)
{
   int slBroj = (double)rand() / (RAND_MAX + 1) * (range_max - range_min) + range_min;
   return slBroj;
}


//nit koja generira promet po svim cestama
void* trafficGenerator(void* arg)
{
    int cesta=0;//koja cesta
    double vrijemeCekanja=0;//koliko sekundi do dolaska sljedeceg vozila na raskrizje

    while (_bProgramState > 0)
    {
       if (_bProgramState==2)
       {
          cesta = rand() % 4;//slucajni odabir ceste
          vrijemeCekanja = RangedRandom(minVrijemeCekanja, maxVrijemeCekanja);//slucajni broj za vrijeme cekanja na novo vozilo

          Sleep(vrijemeCekanja);

          //TODO:lock treba ovdje
          vozilaNaCesti[cesta]++;//dodajem novo vozilo na neku slucajno odabranu cestu
       }
    }

    pthread_exit(NULL);
}

//nit koja radi ispis stanja prometa svakih n sekundi
void* trafficReport(void* arg)
{
    int i=0;

    while (_bProgramState > 0)
    {
       if (_bProgramState==2)
       {
          Sleep(200);//0.2 sekunda

          system("cls");//brisanje konzole win
          //system("clear");//brisanje konzole linux
      
          printf("\nTraffic is running...");

          printf("\nCesta       Broj vozila       Semafor");
          printf("\n===============================================================");

          for (i = 0; i < NUM_ROADS; i++)
          {
             char* svjetloNaSemaforu;
             if (semafor[i]==0)
                svjetloNaSemaforu = "crveno";
             else
                svjetloNaSemaforu = "zeleno";
            
             printf("\n%d       %d          %s", i+1, vozilaNaCesti[i], svjetloNaSemaforu);
          }
       }
    }

    pthread_exit(NULL);
}


int main(int argC, char* argV[])
{  
    pthread_t *thTrafficGenerator;//nit za trafficGenerator
    pthread_t *thTrafficReport;//nit za ispis stanja

    thTrafficGenerator = (pthread_t*)malloc(sizeof(pthread_t));//memorija za trafficGenerator nit
    pthread_create(thTrafficGenerator, NULL, trafficGenerator, NULL);//startanje trafficGenerator niti

    //pokretanje prometa
    _bProgramState = 2;

    pthread_join(*(thTrafficReport), NULL);
    pthread_join(*(thTrafficGenerator), NULL);

    free(thTrafficGenerator);
    free(thTrafficReport);
  
    pthread_exit(NULL);

    return 0;
}

Lack of money is the root of all evil. George Bernard Shaw
 
0 0 hvala 0
17 godina
neaktivan
offline
Re: Visenitna konzolna aplikacija - C

Prouči program na ovoj stranici. Usput, za čekanje koristi funkcije sleep s rezolucijom od jedne sekunde, usleep s rezolucijom od jedne mikrosekunde ili nanosleep s rezolucijom od jedne nanosekunde. Tvoja implementacija funkcije sleep zapravo ne pauzira izvršavanje niti.

The laws of nature are constructed in such a way as to make the universe as interesting as possible. - Freeman Dyson, Imagined Worlds
14 godina
neaktivan
offline
Re: Visenitna konzolna aplikacija - C

Možeš i u main thread-u vrtiti while petlju gdje čitaš pritisnutu tipku.

 

No isto tako, ovo tvoje rješenje mi je sumnjivo.

 

vozilaNaCesti[cesta]++;

 

Ovo ti je i u komentaru napisano da treba zaključati zbog eventualne data race situacije. Upotrijebi kritičnu sekciju i u nju stavi taj dio coda.

Poruka je uređivana zadnji put sri 25.1.2012 11:19 (TracerCPP).
16 godina
offline
Visenitna konzolna aplikacija - C

Hvala obojici na savjetima, sve sto ste rekli je bilo korisno, i na kraju sam sve uspio napraviti da radi kako treba. Ali, izgnjavio sam se skroz jer sam prvo radio u windowsu (VS2010), a onda taj kod prebacio i testirao u Linuxu. Neke stvari naravno nema u jednom ili drugom sustavu, ali najgore mi je kad neke stvari postoje i na win i na linuxu, ali rade drukcije (npr. clock()). Ona moja sleep funkcija na win radi super, dok na Linuxu uopce ne radi...

Na kraju imam 2 verzije koda, al bar sam naucio neke stvari :)

Lack of money is the root of all evil. George Bernard Shaw
 
0 0 hvala 0
1
Nova poruka
E-mail:
Lozinka:
 
vrh stranice