一个简单的超时功能

时间:2012-11-05 19:39:46

标签: c timer

我在产品系列代码中遇到了超时功能,让我感到非常困惑:

int TestTimeOut(unsigned long Timed_Val1, unsigned long Timed_Val2)
{
    Timed_Val2 = Timed_Val1 + (Timed_Val2 * 200);
    if (((Timed_Val1 > Timed_Val2) && (sys_msec < Timed_Val1) && (sys_msec > Timed_Val2)) || ((Timed_Val1 < Timed_Val2) && ((sys_msec < Timed_Val1) || (sys_msec > Timed_Val2))))
        return TRUE;
    return FALSE;
}

以下是它的使用方法:

unsigned long Timeout = sys_msec;
#define MAX_TIMEOUT   15L

    while (!com_eot(1))  //to check if some transmission in progress in COM1
        if (TestTimeOut(Timeout, MAX_TIMEOUT))
            return FALSE;
    return TRUE;

它是如何工作的?我对TestTimeOut()中的3行感到困惑。

2 个答案:

答案 0 :(得分:2)

首先,我重构ab局部变量。

int TestTimeOut(unsigned long Timed_Val1, unsigned long Timed_Val2)
{
    Timed_Val2 = Timed_Val1 + (Timed_Val2 * 200);
    const int a = (Timed_Val1 > Timed_Val2) &&  (sys_msec < Timed_Val1) && (sys_msec > Timed_Val2);
    const int b = (Timed_Val1 < Timed_Val2) && ((sys_msec < Timed_Val1) || (sys_msec > Timed_Val2));
    return a || b;
}

现在这很有趣,Timed_Val2基于Timed_Val1,它们都是unsigned所以Timed_Val2始终是>= Timed_Val1。起初我看不出a没有办法是真的,但正如马克威尔金斯所指出的那样,如果它包裹起来就可以了。

也只有一种情况它们是相同的,那就是Timed_Val2==0我将把它作为特殊情况提取出来以帮助提高可读性。然后,我可以将两个> / <语句分解为if

int TestTimeOut(unsigned long Timed_Val1, unsigned long Timed_Val2)
{
    if (Timed_Val2==0) return FALSE;

    {
      Timed_Val2 = Timed_Val1 + (Timed_Val2 * 200);

      if (Timed_Val1 > Timed_Val2)
      { //this happens when it wraps around past 2^32
        return (sys_msec < Timed_Val1) && (sys_msec > Timed_Val2);
      }
      else
      {
        return (sys_msec < Timed_Val1) || (sys_msec > Timed_Val2);
      }
    }
}

所以我会说这会返回true iff(if和only if)sys_msecTimed_Val1之前或Timed_Val1 + Timed_Val2 * 0.2 seconds之后。

作为最后阶段,现在我将重命名变量并对其进行评论。

//Returns true iff time is before startTime_msec or after timeoutPeriods of 0.2 seconds
//startTime_msec - millisecond value compariable to sys_msec
//timeoutPeriods - the number of timeout periods of 0.2 seconds each
int TestTimeOut(const unsigned long startTime_msec, const unsigned long timeoutPeriods)
{
    if (timeoutPeriods==0) return FALSE;

    {
      const unsigned long maxTime_msec = startTime_msec + (timeoutPeriods * 200);
      if (startTime_msec > maxTime_msec)
      { //this happens when it wraps around past 2^32
        return (sys_msec < startTime_msec) && (sys_msec > maxTime_msec);
      }
      else
      {
        return (sys_msec < startTime_msec) || (sys_msec > maxTime_msec);
      }          
    }
}

这并不是说没有更好的方法可以做到这一点,但至少它现在是可读的。

答案 1 :(得分:2)

检查有些复杂的原因是因为整数翻转的可能性。如果发生这种情况,那么它需要检查的两个部分。具体示例可能有所帮助。例如,如果此系统上的long为32位,并且Timed_Val1的初始值为2 ^ 32-100 = 4294967196,那么Timed_Val2将被计算为2900.所以它就是需要这部分检查的情况类型:

if (((Timed_Val1 > Timed_Val2) && (sys_msec < Timed_Val1) && (sys_msec > Timed_Val2)) || 

在这种情况下,当sys_msec介于val1和val2之间时会发生超时。它需要大于2900且小于4294967196.

Timed_Val2的计算中没有翻转时,条件的另一半是“正常”情况:

((Timed_Val1 < Timed_Val2) && ((sys_msec < Timed_Val1) || (sys_msec > Timed_Val2))))

在这种情况下,超时发生在sys_msec大于val2时或者当它已翻转时,因此小于val1。

但是,所选的变量名称肯定很差。重命名它们是有意义的。