pthread_cond_timedwait()

前端 未结 7 1537
有刺的猬
有刺的猬 2020-12-16 05:22
void wait(int timeInMs)
{
    struct timespec timeToWait;
    timeToWait.tv_sec = 5;
    timeToWait.tv_nsec = timeInMs*1000;

    int rt;

    pthread_mutex_lock(&am         


        
相关标签:
7条回答
  • 2020-12-16 05:58

    That code doesn't sleep, it checks a condition for a while. As you are not probably setting cond ok it just returns immediately.

    If you are not willing to synchronize threads around a signal then pthread_cond _wait is not what you need. Check here how condition variables work.

    if you want to sleep with seconds precision use sleep

    If you want to sleep with microseconds precision use select with timevals.

    0 讨论(0)
  • 2020-12-16 06:08

    Considering you are using timespec, and your goal isn't to synchronize but to wait I'd suggest nanosleep.

    #include <time.h>
    
    .
    .
    .
    
      struct timespec remain;
      remain.tv_sec = 5;
      remain.tv_nsec = timeInMs * 1000;
    
      do {
        if ( nanosleep( &remain, &remain ) == 0 || errno != EINTR ) {
          break;
        }
      } while ( 1 );
    
    .
    .
    .
    
    0 讨论(0)
  • 2020-12-16 06:14

    pthread_cond_timedwait uses absolute time, so need to:

    • use gettimeofday to retrieve current time.
    • timespec.tv_nsec is nanosecond, it can't be large than 1 second.
    • timeval.tv_usec is microsecond (1000 nanoseconds).
    • timeInMs is millisecond: 1 millisecond = 1000 microseconds = 1000 * 1000 nanoseconds.

      void wait(int timeInMs)
      {
          struct timeval tv;
          struct timespec ts;
      
          gettimeofday(&tv, NULL);
          ts.tv_sec = time(NULL) + timeInMs / 1000;
          ts.tv_nsec = tv.tv_usec * 1000 + 1000 * 1000 * (timeInMs % 1000);
          ts.tv_sec += ts.tv_nsec / (1000 * 1000 * 1000);
          ts.tv_nsec %= (1000 * 1000 * 1000);
      
          int n = pthread_cond_timedwait(&condition, &mutex, &ts);
          if (n == 0)
              // TODO: singaled
          else if (n == ETIMEDOUT)
              // TODO: Time out.
      }
      
    0 讨论(0)
  • 2020-12-16 06:15

    Using any variant of sleep, the behavior is not guaranteed. All the threads can also sleep since the kernel is not aware of the different threads.

    A safer and cleaner solution to use is pthread_cond_timedwait. You used the API incorrectly. Here is a better example:

    pthread_mutex_t fakeMutex = PTHREAD_MUTEX_INITIALIZER;
    pthread_cond_t fakeCond = PTHREAD_COND_INITIALIZER;
    
    void mywait(int timeInMs)
    {
        struct timespec timeToWait;
        struct timeval now;
        int rt;
    
        gettimeofday(&now,NULL);
    
    
        timeToWait.tv_sec = now.tv_sec+5;
        timeToWait.tv_nsec = (now.tv_usec+1000UL*timeInMs)*1000UL;
    
        pthread_mutex_lock(&fakeMutex);
        rt = pthread_cond_timedwait(&fakeCond, &fakeMutex, &timeToWait);
        pthread_mutex_unlock(&fakeMutex);
        printf("\nDone\n");
    }
    
    void* fun(void* arg)
    {
        printf("\nIn thread\n");
        mywait(1000);
    }
    
    int main()
    {
        pthread_t thread;
        void *ret;
    
        pthread_create(&thread, NULL, fun, NULL);
        pthread_join(thread,&ret);
    }
    

    You need to specify how much time to wait from current time. Since you were only telling 5 sec and some nano-seconds it found that the time had already passed and did not wait...Please let me know if any more doubts.

    0 讨论(0)
  • 2020-12-16 06:15

    Main reference: http://pubs.opengroup.org/onlinepubs/009695299/functions/pthread_cond_timedwait.html

    FIX of the code of andrewrk above

    I can confirm Adrian May that gettimeofday doesn't function correctly! The code behavior of andrewrk inside an infinite thread like this

    static void * thread_infinite(void * unused) {
    while (1) {
            // compute stuff
            mywait(5);
    }
    

    is unpredictable: it runs approximate 700 times more until it blocks!

    The correct version of the code of andrewrk is:

    pthread_mutex_t fakeMutex = PTHREAD_MUTEX_INITIALIZER;
    pthread_cond_t fakeCond = PTHREAD_COND_INITIALIZER;
    
    void mywait(int timeInS)
    {
        struct timespec ts;
        struct timeval now;
        int rt = 0;
    
    //    gettimeofday(&now,NULL); // DOES NOT FUNCTION CORRECTLY
    //    timeToWait.tv_sec = now.tv_sec+5;
    //    timeToWait.tv_nsec = (now.tv_usec+1000UL*timeInMs)*1000UL;
    
        clock_gettime(CLOCK_REALTIME, &ts);
        ts.tv_sec += timeInS;
    
        pthread_mutex_lock(&fakeMutex);
    
        do {
            rt = pthread_cond_timedwait(&fakeCond, &fakeMutex, &ts);
            }
        while (rt == 0);
    
        pthread_mutex_unlock(&fakeMutex);
    }
    
    0 讨论(0)
  • 2020-12-16 06:17

    The pthread_cond_timedwait function takes an absolute time, not a relative time. It takes the time you want to stop waiting, not how long you want to wait.

    0 讨论(0)
提交回复
热议问题