2012-11-05 43 views
0

我的产品线代码跨超时功能来这得到我真的很困惑:一个简单的超时功能

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行弄糊涂了。谢谢,

+0

是的,那太疯狂了。我会重构它以使用更多的行和一些临时变量。应该变得更清楚。 – weston

回答

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可能是真实的,但正如马克威尔金斯指出的那样,如果环绕它的话也是可以的。

但也有只有一种情况,他们是相同的,但是,当我要解压出来作为一个特殊情况,以帮助可读性。然后,我可以将两个>/<语句分解为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,当且仅当(当且仅当)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); 
     }   
    } 
} 

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

+0

我喜欢你的分析和逻辑步骤。不过,在所有情况下,假设val2> = val1的第一步存在问题。它没有考虑整数溢出。因此,放弃第一个条件是不正确的。 –

+0

@ Mark-Wilkins谢谢你指出。我也看到了我的最终版本的另一个问题,所以明天会改进答案。 – weston

+0

很酷。我喜欢你的逻辑解释和变量名称。 –

2

有点复杂的检查的原因是因为整数翻转的可能性。如果发生这种情况,那么它需要检查的两个部分。一个具体的例子可能有帮助例如,如果这个系统上的长度是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时发生超时。

尽管如此,所选择的变量名称肯定很差。重命名它们是有意义的。

+0

该死的我错过了翻滚! – weston