{"id":5884,"date":"2023-05-27T00:01:07","date_gmt":"2023-05-27T07:01:07","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=5884"},"modified":"2023-05-13T10:05:02","modified_gmt":"2023-05-13T17:05:02","slug":"the-improved-nano_delay-function-i-hope","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=5884","title":{"rendered":"The Improved <em>nano_delay()<\/em> Function (I Hope)"},"content":{"rendered":"<p>Last week&#8217;s <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=5882\">Lesson<\/a> explored using the <em>clock_gettime()<\/em> function to pause program execution for a given number of nanoseconds. The code, however, contains a flaw that may render an inaccurate result.<br \/>\n<!--more--><br \/>\nI&#8217;m not even going to get into the merits of a nanosecond delay feature when the program itself runs faster than the nanosecond clock. Still, this Lesson is just an exercise that hopefully makes a programmer think and write better code.<\/p>\n<p>In the original <em>nano_delay()<\/em> function, the delay is calculated as the current nanosecond value plus the delay:<\/p>\n<p><code>end = res.tv_nsec + ns;<\/code><\/p>\n<p>Variable <code>end<\/code> is the sum of the current nanosecond value (<code>res.tv_nsec<\/code>) plus the <code>ns<\/code> argument, or delay in nanoseconds. The value of <code>end<\/code> determines when the pause is over. For example if the nanosecond delay (value of <code>ns<\/code>) is 1000 and the current nanosecond value (<code>res.tv_nsec<\/code>) is 456789, the function waits until the current nanosecond value becomes greater than 456789 + 1000, or 457789.<\/p>\n<p>Suppose that the value of <code>res.tv_nsec<\/code> is 750,000,000 (commas added for readability). And the delay (<code>ns<\/code>) is 500,000,000, the value of variable <code>end<\/code> is 1,250,000,000. This value is out of range for <code>res.tv_nsec<\/code>. The <em>if<\/em> test in function&#8217;s the endless <em>while<\/em> loop will never be true.<\/p>\n<p>Nanoseconds are billionths of a second. The defined constant <code>MAX_N<\/code> in the original code sets the maximum value for nanoseconds to 999,999,999 (remembering that the count starts with zero). The maximum value of a signed <em>long<\/em> integer is 2,147,483,647, well below the <code>MAX_N<\/code> value. The issue with the overflow isn&#8217;t due to the size of the data type, but the number of nanoseconds in a second.<\/p>\n<p>This code shows may approach to deal with this nanosecond overflow situation. It uses a new variable <code>base<\/code> to track the overflow.<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2023_05_27-Lesson.c\" rel=\"noopener\" target=\"_blank\">2023_05_27-Lesson.c<\/a><\/h3>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n#include &lt;time.h&gt;\r\n\r\n#define MAX_N 999999999L\r\n\r\nvoid nano_delay(long ns)\r\n{\r\n    struct timespec res;\r\n    long end,base;\r\n\r\n    <span class=\"comments\">\/* avoid out of range values *\/<\/span>\r\n    if( ns&lt;1 || ns&gt;MAX_N )\r\n        return;\r\n\r\n    base = 0;\r\n    <span class=\"comments\">\/* obtain the current value *\/<\/span>\r\n    clock_gettime(CLOCK_REALTIME,&amp;res);\r\n    <span class=\"comments\">\/* calculate end time *\/<\/span>\r\n    end = res.tv_nsec + ns;\r\n    if( end&gt;MAX_N )\r\n        base = MAX_N;\r\n    <span class=\"comments\">\/* wait for the end time *\/<\/span>\r\n    while(1)\r\n    {\r\n        clock_gettime(CLOCK_REALTIME,&amp;res);\r\n        if( base )\r\n            res.tv_nsec += base;\r\n        if( res.tv_nsec &gt; end )\r\n            break;\r\n    }\r\n}\r\n\r\nint main()\r\n{\r\n    long delay;\r\n\r\n    for( delay=10; delay&lt;MAX_N; delay*=10 )\r\n    {\r\n        printf(\"Delay = %ld\\n\",delay);\r\n        nano_delay(delay);\r\n    }\r\n\r\n    return(0);\r\n}<\/pre>\n<p>Variable <code>base<\/code> is initialized to zero at Line 15: <code>base = 0<\/code><\/p>\n<p>At Line 20, an <em>if<\/em> test determines whether the <code>end<\/code> value is greater than defined constant <code>MAX_N<\/code>. If true, the <code>base<\/code> is established as <code>MAX_N<\/code>.<\/p>\n<p>In the endless <em>while<\/em> loop, a second <em>if<\/em> test is TRUEwhen the value of <code>base<\/code> isn&#8217;t zero. In this case the end time calculation is made based on the value of <code>res.tv_nsec<\/code> plus <code>base<\/code>.<\/p>\n<p>The silly thing is that the program still runs the same as far as I can tell. Which means all my effort here might be in vain. Still, it was a good thought experiment on how to deal with overflow when the value is less than the maximum data type size, or one billion in this case.<\/p>\n<p>I&#8217;d be interested to see other approaches to handling this situation, or whether it needs to be dealt with at all.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>My attempt to fix an overflow flaw in my original (and possibly useless) <em>nano_delay()<\/em> function. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=5884\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-5884","post","type-post","status-publish","format-standard","hentry","category-main"],"_links":{"self":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/5884","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=5884"}],"version-history":[{"count":3,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/5884\/revisions"}],"predecessor-version":[{"id":5892,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/5884\/revisions\/5892"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5884"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=5884"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=5884"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}