1

My program contains two threads for which they are expected to end. I use a single variable that is shared between threads and this is x and a single mutex. The q key ends the thread

Problems I want to solve:

  1. I want the stars (*) that are displayed one by one on the line now, I want them to be one after the other on the same line
  2. I don't want to have to press enter after q to exit the program. I want it to exit the program immediately when I press q (no additional keys)

What should I change?

P.S (I have two warnings when running the program with gcc program.c -o program -lpthread, but that's not what I'm interested in at the moment, I'll solve it later)

program.c: In function ‘first’:
program.c:24:1: warning: control reaches end of non-void function [-Wreturn-type]
   24 | }
      | ^
program.c: In function ‘second’:
program.c:44:1: warning: control reaches end of non-void function [-Wreturn-type]
   44 | }
      | ^

code:

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

pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_q = PTHREAD_COND_INITIALIZER;

char *x;

void *first(void *arg) {

        x = (char*)malloc(sizeof(char));
        do {
                scanf("%c", x);
                pthread_mutex_lock(&mut);
                if(x[0] == 'q') {
                        pthread_cond_signal(&cond_q);
                }
                pthread_mutex_unlock(&mut);
        } while( x[0] != 'q');
        free(x);
        printf("exited thread 1\n");
}

void *second(void *arg) {

        struct timespec ts;
        int ok = 1;

        pthread_mutex_lock(&mut);
        while(ok) {

                clock_gettime(CLOCK_REALTIME, &ts);
                ts.tv_sec += 1;

                ok = pthread_cond_timedwait(&cond_q, &mut, &ts);
                if(ok == 0) break;
                printf("*\n");

        }
        pthread_mutex_unlock(&mut);
        printf("exited thread 2\n");
}

int main()
{
        pthread_t read;
        pthread_t write;

        pthread_create(&read, NULL, &first,NULL);
        pthread_create(&write, NULL, &second,NULL);
        pthread_join(read, NULL);
        pthread_join(write, NULL);

        pthread_cond_destroy(&cond_q);
        pthread_mutex_destroy(&mut);

        return 0;
}
  • I don't see `x` shared between both threads (not used in `second` or `main`), but if you do it will need to be protected. _I want it to exit the program immediately when I press q (no additional keys)_. This will require a non-standard solution I believe, something like ncurses. Also, not wrong but kind of silly to `malloc` a single char. Just declare `char x;` and forget `malloc`ing. – yano Apr 27 '22 at 15:40
  • This is really two separate questions. I suggest you remove question 2 here. – hyde Apr 27 '22 at 15:43
  • 1
    For unbuffered input on Unix: https://stackoverflow.com/a/1798833/1717300 – hyde Apr 27 '22 at 15:48
  • The title of the question linked to by [hyde](https://stackoverflow.com/users/1717300/hyde) in their [comment](https://stackoverflow.com/questions/72031540/program-that-starts-two-threads-and-waits-for-their-completion#comment127277207_7203154) is [How to avoid pressing enter with `getchar()` for reading a single character only?](https://stackoverflow.com/q/1798511/15168). The top-voted answer is reasonable; the accepted answer is less reasonable. (This deals with your second question — how to type `q` without having to hit the enter key too.) – Jonathan Leffler Apr 27 '22 at 16:24
  • 1
    You should fix those compiler warnings — they are telling you that your code is broken. Add `return 0;` at the end of each function. You are invoking undefined behaviour by not returning a value from the thread functions. You can't afford to risk that. – Jonathan Leffler Apr 27 '22 at 16:27
  • 1
    You cannot guarantee that `first()` will run before `second()` — the allocation of memory for `x` (uninformative name — globals should be named descriptively) in `first()` is unsafe because it is not protected by the mutex. OTOH, the thread in `second()` doesn't actually access `x`, so it isn't shared, despite comments that it is shared. Also, allocating a single character via `malloc()` is hard work; why not just define `static char x;` and use that? There is no obvious benefit to the dynamic allocation and it uses a lot more space that way. – Jonathan Leffler Apr 27 '22 at 16:29
  • Flush your output to display the star immediately: `fflush(stdout)`. – nsilent22 Apr 28 '22 at 21:13

0 Answers0