0
votes

I'm learning to use pthreads, mutexes and condition variables but things aren't going as expected.

MAIN THREAD: runs continuously, signals worker thread, reads from file_A.

WORKER THREAD: sleep until signal received, writes to file_A, back to sleep (should be repeatable)

So I understand a mutex is needed here to prevent both threads from reading/writing to and from the same file. I'm using a condition variable to signal the worker thread.

But for some reason, the worker thread only runs once. Do I need to reset the condition variable or do something else?

Worker thread function:

void* WriteTime(){
    pthread_mutex_lock(&mutex);
    pthread_cond_wait(&condition, &mutex);

    /* Open File, Write to File, Close File */

    pthread_mutex_unlock(&mutex);
}

Main Thread:

pthread_t timeThread;
pthread_create(&timeThread, NULL, &WriteTime, NULL);

while(gameConditionFulfilled == false){
    /* Print status, gets user input into line */

    /* If user enters "time", wake up WORKER_THREAD */

    if(strcmp(line, "time")==0){
        pthread_mutex_lock(&mutex);
        pthread_cond_signal(&condition);

        /* Read from file, print data, close file */ 

        pthread_mutex_unlock(&mutex);
    }
}

Also my understanding of the code above is like this:

  1. Worker thread locks mutex. (Launched before main's loop)
  2. Worker thread cond_wait unlocks mutex and waits for condition.
  3. Main thread locks mutex.
  4. Main thread signals condition.
  5. Worker thread regains mutex lock, writes to file.
  6. Worker thread unlocks mutex.
  7. Main thread regains mutex and locks it.
  8. Main thread reads file.
  9. Main thread unlocks mutex.
  10. Worker thread regains lock?

The behavior is actually:

  1. Main thread reads from file
  2. Worker thread wakes up, writes to file, never runs again
1

1 Answers

1
votes

First off, you would want some sort of loop in WriteTime() -- returning causes pthread_exit() to be called. When pthread_create() starts a thread, it is started as if:

pthread_exit((*func)(arg));

Which raises the second point -- your compiler should have screamed at you about this, since your WriteTime() doesn’t return anything. Warnings are useful; they don’t need to be obeyed, but you should understand why they are presented.

To skip a couple of chapters, the idea of a condition variable is that it protects a “condition”; for example that there is data ready to read or write. You are using them like semaphores, but unlike semaphores, condition variables do not have any memory. Pthread_condition_wait() will only return if pthread_condition_(signal|broadcast)() is called WHILE the thread is waiting. If pthread_condition_signal() is called when nobody is waiting, nothing happens. So the idiomatic use of a condition variable is:

lock(mutex)
while (something_hasn’t_happened) {
    wait(cond, mutex)
}
do something
unlock(mutex)