How does the pthread_cond_timedwait() function work?

Asked

Viewed 102 times

1

The purpose of this function is to show the hours, wait for 2 seconds, and show the hours again to make sure that 2 seconds have passed. I am not using sleeps as this function is to help me understand how the pthread_cond_timedwait function works so I can use it as a synchronization method.

//gcc -Wall -pthread timedwait.c -o  timedwait


#define _OPEN_THREADS                                                           
#include <pthread.h>                                                            
#include <stdio.h>                                                              
#include <time.h>                                                               
#include <errno.h>
#include <stdlib.h>


int main() {                                                                        
  pthread_cond_t cond;                                                          
  pthread_mutex_t mutex;                                                        
  time_t T;                                                                     
  struct timespec t;                                                            

  if (pthread_cond_init(&cond, NULL) != 0) {                                    
    perror("pthread_cond_init() error");                                        
    exit(2);                                                                    
  }                                                                             


  time(&T);                                                                     
  t.tv_sec = T + 2;                                                             
  printf("starting timedwait at %s", ctime(&T));                                
  pthread_cond_timedwait(&cond, &mutex, &t);                                                                                               
  time(&T);                                                                     
  printf("timedwait over at %s", ctime(&T));                                  
}

2 answers

0

That’s how it works:

int main() {
  pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
  pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  time_t T;
  struct timespec t;

  time(&T);
  t.tv_sec = T + 2;
  t.tv_nsec = 0;
  printf("starting timedwait at %s", ctime(&T));
  pthread_mutex_lock(&mutex);
  pthread_cond_timedwait(&cond, &mutex, &t);
  time(&T);
  printf("timedwait over at %s", ctime(&T));
}

I think the main defect of his attempt was to forget to lock the mutex, which is an essential condition for pthread_cond_timedwait() to operate. (He also unlocks the mutex.)

pthread_cond_timedwait() works similar to a Sleep(2) in this example because it waits for the condition variable cond until the maximum time limit specified in the third parameter. Because it is a single-threaded program, no one will call pthread_cond_signal() and the result is that we will always wait 2 seconds, the condition variable just satisfies the caller and does nothing really.

  • I tested now giving lock and Unlock to mutex and did not work, ran the second print, without expecting any second.

  • I tested my code on macos, does Linux need to pick up the time with clock_gettime() instead of time()? Another time I’ll test this, it would be an interesting difference to document.

  • I put here the resolution that works with the help in the English stackoverflow, and the clock_gettime was used, maybe it was that.

  • I tested on Linux now and neither my version nor yours were working. What you solved, for both of them, was to compile with -lpthread. I think in macos pthread is implicit, but not in Linux, and Linux plays the behavior of never waiting for condition when it is compiled without pthread (assumes it is single-threaded).

0

I was helped in stackoverflow English, more information: Stackoverflow English

/ gcc -Wall -pthread timedwait.c -o  exe

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

int main() {
    pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    struct timespec t;
    int result;

    result = pthread_mutex_lock(&mutex);
    if (result != 0) {
        fprintf(stderr, "pthread_mutex_lock: %s\n", strerror(result));
        exit(EXIT_FAILURE);
    }

    result = clock_gettime(CLOCK_REALTIME, &t);
    if (result == -1) {
        perror("clock_gettime");
        exit(EXIT_FAILURE);
    }

    // Return-value check is non-essential here:
    printf("starting timedwait at %s", ctime(&t.tv_sec));

    t.tv_sec += 2;
    result = pthread_cond_timedwait(&cond, &mutex, &t);
    if (result != ETIMEDOUT) {
        fprintf(stderr, "%s\n", strerror(result));
    }

    result = clock_gettime(CLOCK_REALTIME, &t);
    if (result == -1) {
        perror("clock_gettime");
        exit(EXIT_FAILURE);
    }

    // Return-value check is non-essential here:
    printf("timedwait over at %s", ctime(&t.tv_sec));

    // Return-value check is non-essential here, because we'll just exit anyway:
    pthread_mutex_unlock(&mutex);
}
  • On Linux you have to compile with -lpthread to work, and it also fixes "my" version. Quite interesting this case.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.