Windows上的pthread_cond_timedwait过早返回ETIMEDOUT

时间:2012-03-19 19:58:37

标签: windows time pthreads

在pthreads-win32 2.7和2.8下,pthread_cond_timedwait有时会在ETIMEDOUT时过早返回。只有一个等待线程和一个信令线程。我不相信这是条件变量虚假解除阻塞的情况,如问题:pthread_cond_timedwait returning immediately

Win32 pthread实现在内部调用_ftime()来确定当前时间,并将其与将来等待的绝对时间进行比较。这个计时器的准确性是不够的(我认为),因此等待的相对时间通常不正确。假设我要求等待一秒钟:

struct timespec ts;
ts.tv_sec = static_cast<long>(time(NULL) + sec_rel);
ts.tv_nsec = 0;

// OR

struct timespec ts;
struct _timeb currSysTime;
_ftime(&currSysTime);
ts.tv_sec = static_cast<long>(currSysTime.time + sec_rel);
ts.tv_nsec = currSysTime.millitm * 1000000;

if( pthread_cond_timedwait(&m_cond, &m_Mutex, &ts) ) // returns too early 

这两种确定当前时间的方法与pthread代码不能很好地混合,pthread代码计算在给定绝对时间的情况下等待的毫秒数,在ptw32_relmillisecs.c中(参见本文末尾) ptw32_relmillisecs将通常返回少量毫秒,而不是预期的近1000毫秒。

我现在正在做的是用我自己的计时器循环,直到超时真的过去,但我觉得我必须错误地计算未来的绝对时间。


    INLINE DWORD
ptw32_relmillisecs (const struct timespec * abstime)
{
  const int64_t NANOSEC_PER_MILLISEC = 1000000;
  const int64_t MILLISEC_PER_SEC = 1000;
  DWORD milliseconds;
  int64_t tmpAbsMilliseconds;
  int64_t tmpCurrMilliseconds;

 struct _timeb currSysTime;



  /* 
   * Calculate timeout as milliseconds from current system time. 
   */

  /*
   * subtract current system time from abstime in a way that checks
   * that abstime is never in the past, or is never equivalent to the
   * defined INFINITE value (0xFFFFFFFF).
   *
   * Assume all integers are unsigned, i.e. cannot test if less than 0.
   */
  tmpAbsMilliseconds =  (int64_t)abstime->tv_sec * MILLISEC_PER_SEC;
  tmpAbsMilliseconds += ((int64_t)abstime->tv_nsec + (NANOSEC_PER_MILLISEC/2)) / NANOSEC_PER_MILLISEC;

  /* get current system time */
  _ftime(&currSysTime);

  tmpCurrMilliseconds = (int64_t) currSysTime.time * MILLISEC_PER_SEC;
  tmpCurrMilliseconds += (int64_t) currSysTime.millitm;

  if (tmpAbsMilliseconds > tmpCurrMilliseconds)
    {
      milliseconds = (DWORD) (tmpAbsMilliseconds - tmpCurrMilliseconds);
      if (milliseconds == INFINITE)
        {
          /* Timeouts must be finite */
          milliseconds--;
        }
    }
  else
    {
      /* The abstime given is in the past */
      milliseconds = 0;
    }

  return milliseconds;
}

0 个答案:

没有答案