<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>winJade &#187; in depth</title>
	<atom:link href="http://winjade.net/tag/in-depth/feed/" rel="self" type="application/rss+xml" />
	<link>http://winjade.net</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Sun, 27 Jun 2010 23:47:44 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>A lesson on infinite loops</title>
		<link>http://winjade.net/2009/01/lesson-on-infinite-loops/</link>
		<comments>http://winjade.net/2009/01/lesson-on-infinite-loops/#comments</comments>
		<pubDate>Sat, 03 Jan 2009 20:57:35 +0000</pubDate>
		<dc:creator>Bryant Zadegan</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[dev fail]]></category>
		<category><![CDATA[in depth]]></category>
		<category><![CDATA[Infinite Loop]]></category>
		<category><![CDATA[Zune 30]]></category>

		<guid isPermaLink="false">http://www.aeroxp.org/?p=756</guid>
		<description><![CDATA[
pre {
    font-size: medium;
    }

&#160;
&#160;
Yesterday, I took a look at the varying perspectives taken with regards to the Zune 30 debacle. Today, I’ll take a look at what exactly led the Zune 30s to freeze. If you’d like to see the code for the entire driver, click here.
Below the [...]]]></description>
			<content:encoded><![CDATA[<style  TYPE="text/css">
pre {
    font-size: medium;
    }
</style>
<p>&#160;<img style="border-top-width: 0px; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; display: block; border-right-width: 0px" title="quality assurance baby" border="0" alt="quality assurance baby" src="http://winjade.net/wp-content/uploads/2009/01/qualityassurancebaby1.png" width="640" height="480" /></p>
<p>&#160;</p>
<p>Yesterday, <a href="http://www.aeroxp.org/2009/01/zune-30-bug-overinflated/" target="_blank">I took a look</a> at the varying perspectives taken with regards to the Zune 30 debacle. Today, I’ll take a look at what exactly led the Zune 30s to freeze. If you’d like to see the code for the entire driver, <a href="http://pastie.org/349916">click here</a>.</p>
<p>Below the fold lies a sufficiently sized code sample with everything you’ll need to understand what happened with the Zune 30 bug.</p>
<p><script type="text/javascript">
digg_url = 'http://www.aeroxp.org/2009/01/lesson-on-infinite-loops/';
</script><br />
<script src="http://digg.com/tools/diggthis.js" type="text/javascript"></script> </p>
<p> <span id="more-756"></span>
</p>
<p>Relevant code is non-gray code:</p>
<blockquote><pre><font color="#ff00ff"><font color="#000000">#</font>define</font> <font color="#000080">ORIGINYEAR</font> <font color="#ff0000">1980</font> <font color="#000000">
<font color="#008000">BOOL</font> ConvertDays(<font color="#008000">UINT32</font> days<font color="#808080">, SYSTEMTIME* lpTime</font>)
{
    <font color="#008000">int</font> <font color="#808080">dayofweek, month,</font> year;
    <font color="#808080">UINT8 *month_tab;</font>

    <font color="#808080">//Calculate current day of the week
    dayofweek = GetDayOfWeek(days);</font>

    year = <font color="#000080">ORIGINYEAR</font>;

    <font color="#800000">while</font> (days &gt; <font color="#ff0000">365</font>)
    {
        <font color="#800000">if</font> (IsLeapYear(year))
        {
            <font color="#800000">if</font> (days &gt; <font color="#ff0000">366</font>)
            {
                days -= <font color="#ff0000">366</font>;
                year += <font color="#ff0000">1</font>;
            }
        }
        <font color="#800000">else</font>
        {
            days -= <font color="#ff0000">365</font>;
            year += <font color="#ff0000">1</font>;
        }
    }

<font color="#808080">    // Determine whether it is a leap year
    month_tab = (UINT8 *)((IsLeapYear(year))? monthtable_leap : monthtable);

    for (month=0; month&lt;12; month++)
    {
        if (days &lt;= month_tab[month])
            break;
        days -= month_tab[month];
    }

    month += 1;

    lpTime-&gt;wDay = days;
    lpTime-&gt;wDayOfWeek = dayofweek;
    lpTime-&gt;wMonth = month;
    lpTime-&gt;wYear = year;

    return TRUE;
</font>}</font></pre>
</blockquote>
<p>So what’s the purpose of the while loop? To put it simply, it’s designed to get the number of years from the number of days since 1980 as well as a remainder of days out of the current year. Well, let’s look at how the code plays out in my confusingly simple <em>While Loop in Plain English™</em>. Keep in mind that you’re <em>never </em>supposed to retry the loop without committing some sort of action which will ultimately exit the loop:</p>
<ol>
<li>year is set to ORIGINYEAR. Since ORIGINYEAR is 1980, any addition to year is added on top of 1980. This is fine because the hardware is passing the number of days since January 1, 1980. </li>
<li>Is the number of days greater than 365? If so, proceed. Otherwise, skip to number 6. </li>
<li>Is the current year a leap year? If so, proceed. Otherwise, subtract 365 from the number of days, add 1 to the number of years, and skip to number 5. </li>
<li>Is the number of days greater than 366? If so, subtract 366 from the number of days, add 1 to the number of years, and proceed. </li>
<li>retry number 2. </li>
<li>…</li>
<li>Profit? </li>
</ol>
<p>The problem lies in the fact that there is one case which can never escape the loop. If it’s a leap year, the number 366 will stay within the loop forever because 366 will never be greater than 366, but 366 will also always be greater than 365. 366 days will pass through, in our Plain English While Loop, without having any action committed upon it.</p>
<p>There’s a very quick solution to this: Since 366 is a valid remainder of days in a leap year (December 31 is the 366th day in a leap year), 366 can technically exit the loop without any problems. All we need to do is add a way to exit the loop when the number of days is 366. Let’s see how things go with this new breakpoint:</p>
<ol>
<li>year is set to ORIGINYEAR. Since ORIGINYEAR is 1980, any addition to year is added on top of 1980. This is fine because the hardware is passing the number of days since January 1, 1980. </li>
<li>Is the number of days greater than 365? If so, proceed. Otherwise, skip to number 6. </li>
<li>Is the current year a leap year? If so, proceed. Otherwise, subtract 365 from the number of days, add 1 to the number of years, and skip to number 5. </li>
<li>Is the number of days greater than 366? If so, subtract 366 from the number of days, add 1 to the number of years, and proceed. Otherwise, skip to number 6. </li>
<li>retry number 2. </li>
<li>…</li>
<li>Profit!</li>
</ol>
<p>Thanks to the break (represented by “Otherwise, skip to number 6”), 366 days can escape the loop properly. This would lead to the end result for December 31, 2008 being years == 2008 and days == 366.</p>
<p>This is what the break would look in the while loop:</p>
<blockquote>
<pre><font color="#000000">    <font color="#800000">while</font> (days &gt; <font color="#ff0000">365</font>)
    {
        <font color="#800000">if</font> (IsLeapYear(year))
        {
            <font color="#800000">if</font> (days &gt; <font color="#ff0000">366</font>)
            {
                days -= <font color="#ff0000">366</font>;
                year += <font color="#ff0000">1</font>;
            }
            <font color="#800000">else</font>
            {
                <font color="#800000">break;</font>
            }
        }
        <font color="#800000">else</font>
        {
            days -= <font color="#ff0000">365</font>;
            year += <font color="#ff0000">1</font>;
        }
    }
</font></pre>
</blockquote>
<p>Clarifying one quick thing: A number of people on outlets such as Digg suggested that changing “<font color="#800000">if</font> (days &gt; <font color="#ff0000">366</font>)” to “<font color="#800000">if</font> (days &gt;= <font color="#ff0000">366</font>)”:</p>
<p><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; display: inline; border-right-width: 0px" title="QAdigg" border="0" alt="QAdigg" src="http://winjade.net/wp-content/uploads/2009/01/qadigg.png" width="660" height="158" /></p>
<p>The problem with doing this is that the end result, upon hitting “<font color="#800000">if</font> (days &gt;= <font color="#ff0000">366</font>)” with the value 366, one would end up with the year going up by one and the operation “<font color="#ff0000">366 –</font>= <font color="#ff0000">366</font>” playing out. End result: December 31 of the leap year is suddenly January 0 of the following year.</p>
<p>&#160;</p>
<p><strong>Extra credit:</strong> This loop can be fixed such that the loop’s condition is based on the year’s status as a leap year. The change needed is simple:</p>
<blockquote>
<pre><font color="#000000">    <font color="#800000">while</font> (days &gt; (IsLeapYear(year) ? <font color="#ff0000">366</font> : <font color="#ff0000">365</font>))
    <font color="#008080">//The above line basically says “Is it a leap year? Check days against 366.
    //Otherwise, check it against 365”</font>
    {
        <font color="#800000">if</font> (IsLeapYear(year))
        {
            days -= <font color="#ff0000">366</font>;
            year += <font color="#ff0000">1</font>;
            <font color="#008080">/*You’ll notice we no longer need a break. The loop condition now
             *checks the days properly. Because the loop properly checks
             *whether days is greater than 365 or 366, the second days &gt; 366
             *check is no longer needed. */</font>
        }
        <font color="#800000">else</font>
        {
            days -= <font color="#ff0000">365</font>;
            year += <font color="#ff0000">1</font>;
        }
    }
</font></pre>
</blockquote>
<p>&#160;</p>
<p>However, if this change is made, IsLeapYear() is now being called twice. This is inefficient, especially on small devices (like the devices which would be using this driver). In order to reduce the number of times IsLeapYear() is being called, it would be best to store the value of IsLeapYear() in a variable.</p>
<blockquote>
<pre><font color="#000000">    <font color="#008000">int</font> leap = IsLeapYear(year);
    <font color="#008080">//leap is determined before the loop begins.
    //In this case, it would be true (1980 is a leap year)</font>
    <font color="#800000">while</font> (days &gt; (leap ? <font color="#ff0000">366</font> : <font color="#ff0000">365</font>))
    {
        <font color="#800000">if</font> (leap)
        {
            days -= <font color="#ff0000">366</font>;
            year += <font color="#ff0000">1</font>;
        }
        <font color="#800000">else</font>
        {
            days -= <font color="#ff0000">365</font>;
            year += <font color="#ff0000">1</font>;
        }
        leap = IsLeapYear(year);
        <font color="#008080">//leap is determined again now that the year has changed.</font>
    }
</font></pre>
</blockquote>
<p>This can actually be reduced even further. If you look at how the if/else statement is operating, you can see that it’s basically saying “If it’s a leap year, subtract 366. Otherwise, subtract 365,” which is similar to the while loop’s condition!</p>
<blockquote>
<pre><font color="#000000">    <font color="#008000">int</font> leap = IsLeapYear(year);
    <font color="#800000">while</font> (days &gt; (leap ? <font color="#ff0000">366</font> : <font color="#ff0000">365</font>))
    {
        days -= (leap ? <font color="#ff0000">366</font> : <font color="#ff0000">365</font>);
        <font color="#008080">//days is equal to days - 366 if it's a leap year,
        //                 days - 365 if it isn't.</font>
        year += <font color="#ff0000">1</font>;
        leap = IsLeapYear(year);
    }
</font></pre>
</blockquote>
<p>If you wanted to reduce the number of times (leap ? <font color="#ff0000">366</font> : <font color="#ff0000">365</font>) is checked, you could do this instead:</p>
<blockquote>
<pre><font color="#000000">    <font color="#008000">int</font> daysThisYear = (IsLeapYear(year) ? <font color="#ff0000">366</font> : <font color="#ff0000">365</font>);
    <font color="#008080">//The number of days in the current year is now calculated instead. </font>
    <font color="#800000">while</font> (days &gt; daysThisYear)
    {
        days -= daysThisYear;
        year += <font color="#ff0000">1</font>;
        daysThisYear = (IsLeapYear(year) ? <font color="#ff0000">366</font> : <font color="#ff0000">365</font>);
    }
</font></pre>
</blockquote>
<p>It’s questionable whether or not this code is any better than the original solution with the break, but this would be the “proper” way to do it (instead of using an arbitrary break in your code). It’s also easier to understand if you know C.</p>
<p>The irony in all of this is that this specific driver is used in multiple Windows CE devices, not just the Zune. This is why quality assurance is so necessary.</p>
<p><strong>There are three morals here: </strong></p>
<ol>
<li><strong>Test every condition which could happen in every single loop in your code </strong>(though, as Matt Boehm points out in the comments, this might be a <a href = "http://www.aeroxp.org/2009/01/lesson-on-infinite-loops/#comment-831">tad bit hard</a>). </li>
<li><strong>Don’t visit Digg for programming advice. What you’ll hear is questionable at best</strong> </li>
<li><strong>Make your code easy to read for other developers.</strong> </li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://winjade.net/2009/01/lesson-on-infinite-loops/feed/</wfw:commentRss>
		<slash:comments>157</slash:comments>
		</item>
	</channel>
</rss>
