Simple timeout function

I came across a timeout function in the product line code, which confused me a lot:

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; } 

And here is how it is used:

 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; 

How it works? I am completely confused by the three lines in TestTimeOut (). Thanks,

0
source share
2 answers

First, I will reorganize the local variables a and b .

 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; } 

Now this is interesting, Timed_Val2 based on Timed_Val1 , they are both unsigned , so Timed_Val2 always >= Timed_Val1 . At first I could not understand that a might be true, but, as Mark Wilkins points out, he can if he turns around.

There is also only one case where they are equal, that is, when Timed_Val2==0 I am going to extract this as a special case to help readability. Then I can decompose the two > / < if into 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); } } } 

So, I would say that this returns true iff (if and only if) sys_msec before Timed_Val1 or after Timed_Val1 + Timed_Val2 * 0.2 seconds .

As a final step, I would now rename the variables and comment on this.

 //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); } } } 

This does not mean that there is no better way to do this, but at least now it can be read.

+2
source

The reason for the somewhat complicated test is due to the possibility of integer rollovers. If this happens, then two parts of the test are needed. A concrete example may help. If, for example, there is a long 32-bit in this system, and the initial value of Timed_Val1 is 2 ^ 32-100 = 4294967196, then Timed_Val2 will be calculated as 2900. Thus, this is the type of situation that this part of the test requires:

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

In this situation, a timeout occurs when sys_msec is between val1 and val2. It should be more than 2900 and less than 4294967196.

The other half of the condition is a โ€œnormalโ€ situation where there is no rollover when calculating Timed_Val2 :

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

In this case, a timeout occurs when sys_msec greater than val2 OR when it is flipped and therefore less than val1.

The selected variable names are certainly bad. It would be wise to rename them.

+2
source

Source: https://habr.com/ru/post/1446718/


All Articles