Thread: help exercise thread posix , C

  1. #1
    Registered User
    Join Date
    May 2020
    Posts
    9

    help exercise thread posix , C

    hi I'm doing a program with posix threads but my eyes are crossing ... This program "simulates" a bus that moves in 2 stops and at each stop a maximum of 4 tourists go up (the total tourists are 5). The bus leaves from the station where 4 tourists get on (the fifth is in the historic center) and arrives at the historic center where tourists get out of the bus, make a "tour" of 2 seconds and then return to the bus. Entry into the tourist bus is random (I don't have to use a list). For me who started the c recently, threads are a really complicated topic, this is the best I managed to do and obviously it doesn't work ... I would be grateful if someone could help me by showing me how it can be done ... thanks
    ps leave out the error handling, I'll take care of that once the program is finished.




    Code:
    #include<stdio.h>
    
    #include<sys/stat.h>
    
    #include<errno.h>
    
    #include<stdlib.h>
    
    #include<dirent.h>
    
    #include<stdarg.h>
    
    #include<limits.h>
    
    #include<string.h>
    
    #include<time.h>
    
    #include<pthread.h>
    
    #include<stdint.h>
    
    #include<unistd.h>
    
    #define CAPMAX 4
    int fila = 0;
    
    pthread_mutex_t mtx1;
    
    pthread_mutex_t mtx2;
    
    pthread_cond_t enter_tourist;
    
    pthread_cond_t exit_tourist;
    
    void Pthread_mutex_lock(pthread_mutex_t * mtx)
    {
    
    }
    
    void Pthread_mutex_unlock(pthread_mutex_t * mtx)
    {
    
    }
    
    void *bus(void *arg)
    {
    
      int id = (intptr_t) arg;
    
      while (1) {
    
        Pthread_mutex_lock(&mtx1);
    
        printf("[BUS]BUS IS LEAVING \n");
    
        printf("[BUS]CURRENT STOP : STATION\n");
    
        printf("[BUS]TOURISTS CAN GO UP \n");
    
        Pthread_mutex_lock(&mtx1);
    
        pthread_cond_wait(&enter_tourist, &mtx1);
    
        Pthread_mutex_unlock(&mtx1);
    
        sleep(2);
    
        Pthread_mutex_lock(&mtx2);
    
        printf("[BUS]CURRENT STOP BUS : STORIC CENTRE\n");
    
        printf("[BUS]TURISTS CAN GET OFF\n");
    
        printf("[BUS]BUS IS RESTARTING\n");
    
        Pthread_mutex_lock(&mtx2);
    
        pthread_cond_wait(&exit_tourist, &mtx2);
    
        Pthread_mutex_unlock(&mtx2);
    
      }
    
      pthread_exit(NULL);
      return NULL;
    }
    
    void *tourist(void *arg)
    {
    
      int id = (intptr_t) arg;
    
      sleep(2);
    
      while (1) {
    
        sleep(2);
    
        if (fila < CAPMAX) {
    
          Pthread_mutex_lock(&mtx1);
    
          pthread_cond_signal(&enter_tourist);
    
          fila++;
    
          printf("[TOURSIST %d] ENTER IN THE BUS\n", id);
    
          Pthread_mutex_unlock(&mtx1);
    
        }
    
        else if (fila == CAPMAX) {
    
          Pthread_mutex_lock(&mtx2);
    
          pthread_cond_signal(&exit_tourist);
    
          fila--;
    
          printf("[TOURIST %d] GETS OFF THE BUS \n", id);
    
          Pthread_mutex_unlock(&mtx2);
        }
    
        sleep(2);
    
      }
    
      pthread_exit(NULL);
      return NULL;
    
    }
    
    int main(void)
    {
    
      pthread_t threads;
    
      pthread_mutex_init(&mtx1, NULL);
    
      pthread_mutex_init(&mtx2, NULL);
    
      pthread_cond_init(&enter_tourist, NULL);
    
      pthread_cond_init(&exit_tourist, NULL);
    
      int number_turists = 5, i = 0;
    
      for (; i < number_turists; i++) {
    
        pthread_create(&threads, NULL, tourist, (void *) (intptr_t) i);
    
      }
    
      pthread_create(&threads, NULL, bus, (void *) (intptr_t) 0);
    
      pthread_exit(NULL);
    
      return 0;
    
    }
    Last edited by Salem; 05-21-2020 at 12:55 PM. Reason: removed crayola

  2. #2
    Registered User
    Join Date
    May 2020
    Posts
    9
    this is an example of output ... clearly the sequence is wrong ... tourists should all go down and then go up again, even the fifth tourist does what he wants .....


    [BUS]BUS IS LEAVING
    [BUS]CURRENT STOP : STATION
    [BUS]TOURISTS CAN GO UP
    [TOURSIST 4] ENTER IN THE BUS
    [TOURSIST 3] ENTER IN THE BUS
    [TOURSIST 2] ENTER IN THE BUS
    [TOURSIST 1] ENTER IN THE BUS
    [TOURIST 0] GETS OFF THE BUS
    [BUS]CURRENT STOP BUS : STORIC CENTRE
    [BUS]TURISTS CAN GET OFF
    [BUS]BUS IS RESTARTING
    [TOURSIST 4] ENTER IN THE BUS
    [TOURIST 3] GETS OFF THE BUS
    [TOURSIST 2] ENTER IN THE BUS
    [TOURIST 1] GETS OFF THE BUS
    [BUS]BUS IS LEAVING
    [BUS]CURRENT STOP : STATION
    [BUS]TOURISTS CAN GO UP
    [TOURSIST 0] ENTER IN THE BUS
    [BUS]CURRENT STOP BUS : STORIC CENTRE
    [BUS]TURISTS CAN GET OFF
    [BUS]BUS IS RESTARTING
    [TOURIST 4] GETS OFF THE BUS
    [TOURSIST 3] ENTER IN THE BUS
    [TOURIST 2] GETS OFF THE BUS
    [TOURSIST 1] ENTER IN THE BUS
    [TOURIST 0] GETS OFF THE BUS
    [BUS]BUS IS LEAVING
    [BUS]CURRENT STOP : STATION
    [BUS]TOURISTS CAN GO UP
    [TOURSIST 4] ENTER IN THE BUS
    [TOURIST 3] GETS OFF THE BUS
    [TOURSIST 2] ENTER IN THE BUS
    [TOURIST 1] GETS OFF THE BUS

    etc..

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,169
    I would suggest starting with a simple example, then adapt slowly towards your goal.
    Code:
    #include <stdio.h>
    #include <unistd.h>
    #include <pthread.h>
    
    pthread_cond_t c_ping = PTHREAD_COND_INITIALIZER;
    pthread_cond_t c_pong = PTHREAD_COND_INITIALIZER;
    pthread_mutex_t m_ping = PTHREAD_MUTEX_INITIALIZER;
    pthread_mutex_t m_pong = PTHREAD_MUTEX_INITIALIZER;
    
    void *player1( void *p ) {
      for ( int i = 0 ; i < 5 ; i++ ) {
        pthread_mutex_lock(&m_ping);
        pthread_cond_wait(&c_ping, &m_ping);
        printf("Ping...\n");
        sleep(1);
        pthread_cond_signal(&c_pong);
        pthread_mutex_unlock(&m_ping);
      }
      return NULL;
    }
    
    void *player2( void *p ) {
      for ( int i = 0 ; i < 5 ; i++ ) {
        pthread_mutex_lock(&m_pong);
        pthread_cond_wait(&c_pong, &m_pong);
        printf("Pong...\n");
        sleep(2);
        pthread_cond_signal(&c_ping);
        pthread_mutex_unlock(&m_pong);
      }
      return NULL;
    }
    
    int main ( ) {
      pthread_t t1, t2;
      int a = pthread_create(&t1, NULL, player1, NULL);
      int b = pthread_create(&t2, NULL, player2, NULL);
      printf("%d %d\n", a, b);
    
      printf("Start the game\n");
      pthread_cond_signal(&c_ping);
    
      int x = pthread_join(t1,NULL);
      int y = pthread_join(t2,NULL);
      printf("%d %d\n", x, y);
    }
    
    
    $ gcc -g main.c -pthread
    $ ./a.out 
    0 0
    Start the game
    Ping...
    Pong...
    Ping...
    Pong...
    Ping...
    Pong...
    Ping...
    Pong...
    Ping...
    Pong...
    0 0
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Registered User
    Join Date
    May 2020
    Posts
    9
    thank you for the example that helps me better understand the topic ....
    I tried to repair the script but c but I just can't make it work now I print this


    [BUS] BUS IS LEAVING
    [BUS] CURRENT STOP: STATION
    [BUS] TOURISTS CAN GO UP
    [TOURSIST 4] ENTER IN THE BUS
    [TOURSIST 3] ENTER IN THE BUS
    [TOURSIST 2] ENTER IN THE BUS
    [TOURSIST 1] ENTER IN THE BUS
    [BUS] CURRENT STOP BUS: STORIC CENTER
    [BUS] TURISTS CAN GET OFF
    [BUS] BUS IS RESTARTING
    [TOURIST 4] GETS OFF THE BUS
    [BUS] BUS IS LEAVING
    [BUS] CURRENT STOP: STATION
    [BUS] TOURISTS CAN GO UP
    [TOURSIST 4] ENTER IN THE BUS
    [BUS] CURRENT STOP BUS: STORIC CENTER
    [BUS] TURISTS CAN GET OFF
    [BUS] BUS IS RESTARTING
    [TOURIST 4] GETS OFF THE BUS
    [BUS] BUS IS LEAVING
    etch ...


    Code:
    #include<stdio.h> #include<sys/stat.h> #include<errno.h> #include<stdlib.h> #include<dirent.h> #include<stdarg.h> #include<limits.h> #include<string.h> #include<time.h> #include<pthread.h> #include<stdint.h> #include<unistd.h> #define CAPMAX 4 int var1=0; int var2=0; int a=0; pthread_mutex_t mtx; pthread_cond_t enter_tourist; pthread_cond_t exit_tourist; void Pthread_mutex_lock(pthread_mutex_t *mtx){ } void Pthread_mutex_unlock(pthread_mutex_t *mtx){ } void *bus(void *arg){ int id = (intptr_t)arg; while(1){ Pthread_mutex_lock(&mtx); var1=1; printf("[BUS]BUS IS LEAVING \n"); printf("[BUS]CURRENT STOP : STATION\n"); printf("[BUS]TOURISTS CAN GO UP \n"); Pthread_mutex_lock(&mtx); pthread_cond_wait(&enter_tourist,&mtx); sleep(2); printf("[BUS]CURRENT STOP BUS : STORIC CENTRE\n"); printf("[BUS]TURISTS CAN GET OFF\n"); printf("[BUS]BUS IS RESTARTING\n"); var1=2; pthread_cond_wait(&exit_tourist,&mtx); Pthread_mutex_unlock(&mtx); } pthread_exit(NULL); return NULL; } void *tourist(void *arg){ int id=(intptr_t)arg; while (1){ sleep(2); Pthread_mutex_lock(&mtx); if (var1==1){ if(var2<4){ pthread_cond_signal(&enter_tourist); var2++; printf("[TOURSIST %d] ENTER IN THE BUS\n",id); } } else if(var1==2) { if(var2==4){ pthread_cond_signal(&exit_tourist); var2--; printf("[TOURIST %d] GETS OFF THE BUS \n",id); } } Pthread_mutex_unlock(&mtx); } sleep(2); pthread_exit(NULL); return NULL; } int main(void){ pthread_t threads; pthread_mutex_init(&mtx,NULL); pthread_mutex_init(&mtx,NULL); pthread_cond_init(&enter_tourist,NULL); pthread_cond_init(&exit_tourist,NULL); int number_turists=5,i=0; for(;i<number_turists;i++){ pthread_create(&threads,NULL,tourist,(void *)(intptr_t)i); } pthread_create(&threads,NULL,bus,(void *)(intptr_t)0); pthread_exit(NULL); return 0; }







  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,169
    Please paste your code as text, not whatever weird markup you're using.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Registered User
    Join Date
    May 2020
    Posts
    9


    please can you help me, i can't get a spider out of the hole ...

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,169
    1. Better indentation - Indentation style - Wikipedia
    Pick a style and stick to it.
    In particular, do not mix spaces and tabs. Your code editor might make a decent job of it, but as soon as you post it / print it / give it to someone else who doesn't have your clever editor, it looks like dog food.

    2. Better variable names.
    Just how meaningless is var1 = 1 ?

    Example
    Code:
    #include <stdio.h>
    #include <unistd.h>
    #include <pthread.h>
    
    #define NUM_TOURISTS  5
    
    enum locations {
      AT_STATION,
      TRAVEL_TO_CENTRE,
      AT_CENTRE,
      TRAVEL_TO_STATION,
    };
    const char *str_locations[] = {
      "AT_STATION",
      "TRAVEL_TO_CENTRE",
      "AT_CENTRE",
      "TRAVEL_TO_STATION"
    };
    
    enum locations bus_location = AT_STATION;
    
    enum locations tourist_locations[NUM_TOURISTS] = {
      AT_STATION,
      AT_STATION,
      AT_STATION,
      AT_STATION,
      AT_CENTRE
    };
    
    pthread_cond_t c_stopped = PTHREAD_COND_INITIALIZER;
    pthread_mutex_t m_stopped = PTHREAD_MUTEX_INITIALIZER;
    
    void *bus ( void *p ) {
      while( 1 ) {
        printf("Bus %s\n", str_locations[bus_location]);
        if( bus_location == AT_CENTRE || bus_location == AT_STATION ) {
          // tell all the passengers who might be waiting
          pthread_cond_broadcast(&c_stopped);
        }
        sleep(2);
        // go to the other stop
        if ( bus_location == TRAVEL_TO_STATION ) {
          // loop back to the beginning
          bus_location = AT_STATION;
        } else {
          // on to the next stop
          bus_location++;
        }
      }
    
      return NULL;
    }
    
    void *tourist( void *p ) {
      int id = (intptr_t)p;
    
      printf("tourist %d waiting for bus at %s\n", id, str_locations[tourist_locations[id]]);
      while( 1 ) {
        pthread_mutex_lock(&m_stopped);
        pthread_cond_wait(&c_stopped,&m_stopped);
        // Bus just told us it reached a stop
        if( tourist_locations[id] == bus_location ) {
          printf("tourist %d using the bus\n", id);
        }
        pthread_mutex_unlock(&m_stopped);
        sleep(1);
      }
    
      return NULL;
    }
    
    int main( ) {
      pthread_t thread;
      pthread_create(&thread, NULL, bus, NULL);
      for(int i = 0 ; i < NUM_TOURISTS ; i++ ) {
        pthread_create(&thread, NULL, tourist, (void*)(intptr_t)i);
      }
      pthread_exit(NULL);
    }
    
    
    $ ./a.out 
    Bus AT_STATION
    tourist 0 waiting for bus at AT_STATION
    tourist 1 waiting for bus at AT_STATION
    tourist 2 waiting for bus at AT_STATION
    tourist 3 waiting for bus at AT_STATION
    tourist 4 waiting for bus at AT_CENTRE
    Bus TRAVEL_TO_CENTRE
    Bus AT_CENTRE
    tourist 4 using the bus
    Bus TRAVEL_TO_STATION
    Bus AT_STATION
    tourist 0 using the bus
    tourist 1 using the bus
    tourist 2 using the bus
    tourist 3 using the bus
    Bus TRAVEL_TO_CENTRE
    Bus AT_CENTRE
    tourist 4 using the bus
    Bus TRAVEL_TO_STATION
    Bus AT_STATION
    tourist 0 using the bus
    tourist 1 using the bus
    tourist 2 using the bus
    tourist 3 using the bus
    Bus TRAVEL_TO_CENTRE
    Bus AT_CENTRE
    tourist 4 using the bus
    Now all you need to do is when a tourist gets on the bus at the station, they get off the bus at the centre.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  8. #8
    Registered User
    Join Date
    Jun 2020
    Posts
    4
    Quote Originally Posted by Salem View Post
    I would suggest starting with a simple example, then adapt slowly towards your goal.
    Code:
    #include <stdio.h>
    #include <unistd.h>
    #include <pthread.h>
    
    pthread_cond_t c_ping = PTHREAD_COND_INITIALIZER;
    ....
    Hi,

    I like the ping pong idea as a simple starter. But there are problems with how you use the signaling.
    If, e.g., you add a sleep(1) as the first thing player1 does, the game will never start, as player1 misses the signal.
    The pthread_cond_* functions are really only useful in conjunction with a state variable or counter (and a mutex, of course).

    I took the liberty of changing your code quite a bit, wrapping all the cond/mutex stuff in ball_* functions.

    (In real life, one would probably use the sem_* functions from semaphore.h instead, but I think 'rolling-your-own' makes more sense in order to learn the concepts.)

    Oh, yeah, and I managed to build in a race condition myself (see comments in code). I'll leave it as an exercise for the OP to fix that ;oP
    Multithreading is hard

    Cheers,

    Rupert

    Code:
    #include <stdio.h>
    #include <pthread.h>
    #include <unistd.h>
     
    #define PING    1
    #define PONG    2
    
    
    struct Ball {
        int             state; /* PING or PONG */
        int             quit;  /* stop playing */
        pthread_cond_t  cond;
        pthread_mutex_t mutex;
    };
    
    
    static struct Ball ball;
    
    
    
    
    void ball_init(struct Ball *ball, int state)
    {
        ball->state = state;
        ball->quit = 0;
        pthread_cond_init(&ball->cond, NULL);
        pthread_mutex_init(&ball->mutex, NULL);
    }
    
    
    int ball_wait(struct Ball *ball, int state)
    {
        /* wait forever until ball has expected state */
        /* or 'quit' has been set                     */
    
    
        pthread_mutex_lock(&ball->mutex);
        while (ball->state != state && !ball->quit)
            pthread_cond_wait(&ball->cond, &ball->mutex);
        pthread_mutex_unlock(&ball->mutex);
        return !ball->quit;
    }
    
    
    void ball_set(struct Ball *ball, int state)
    {
        pthread_mutex_lock(&ball->mutex);
        ball->state = state;
        pthread_cond_signal(&ball->cond);
        pthread_mutex_unlock(&ball->mutex);
    }
    
    
    void ball_quit(struct Ball *ball)
    {
        pthread_mutex_lock(&ball->mutex);
        ball->quit = 1;
        pthread_cond_broadcast(&ball->cond);
        pthread_mutex_unlock(&ball->mutex);
    }
    
    
    
    
    void* player1(void *p)
    {
        int i;
    
    
        /* Player1 is the leader who decides how long the game is played. */
        /* Doesn't even bother to check if ball_wait() returns true.      */
    
    
        for (i = 0; i < 5 ;i++) {
            ball_wait(&ball, PONG);
            printf("Ping..."); 
            fflush(stdout);
            ball_set(&ball, PING);
        }
        return NULL;
    }
     
    
    
    void* player2(void *p)
    {
        /* Player2 plays as long as player1 wants to. If ball_wait() returns */
        /* false, 'quit' had been set. */
    
    
        while (ball_wait(&ball, PING)) {
            printf("Pong\n"); 
            fflush(stdout);
            ball_set(&ball, PONG);
            /* Uncomment this sleep to discover a race condition with */
            /* how we handle 'quit'! */
            /* sleep(1);*/
        }
        return NULL;
    }
     
    
    
    int main (void)
    {
        pthread_t t1, t2;
    
    
        ball_init(&ball, PONG);
    
    
        printf("Start the game\n");
        fflush(stdout);
    
    
        pthread_create(&t1, NULL, player1, NULL);
        pthread_create(&t2, NULL, player2, NULL);
     
        pthread_join(t1,NULL);  /* wait for player1 to finish */
        ball_quit(&ball);       /* let player2 know that game is over */
        pthread_join(t2,NULL);
    
    
        return 0;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Using POSIX thread in Linux
    By muthus in forum Linux Programming
    Replies: 1
    Last Post: 01-19-2008, 05:24 PM
  2. getting status of a posix thread
    By fragglerock in forum C Programming
    Replies: 1
    Last Post: 09-24-2007, 04:12 PM
  3. posix thread help
    By bomberto in forum C++ Programming
    Replies: 1
    Last Post: 10-15-2006, 02:10 AM
  4. Posix Thread Programming
    By reddybk1 in forum C Programming
    Replies: 8
    Last Post: 10-14-2004, 04:51 PM
  5. Posix Thread programming
    By reddybk1 in forum C++ Programming
    Replies: 1
    Last Post: 10-13-2004, 11:40 PM

Tags for this Thread