[
  {
    "path": ".gitignore",
    "content": ".settings\n.project\nnode_modules\nmisc\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\n\n# test on node version 0.10.35\nnode_js:\n  - 0.10.35\n\n"
  },
  {
    "path": "LICENSE.txt",
    "content": "Copyright (c) 2013-2015, Kevin Briggs\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\nPERFORMANCE OF THIS SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# nanotimer\n# Current Version - 0.3.15\n\n![](https://api.travis-ci.org/Krb686/nanoTimer.png)\n\n[![NPM](https://nodei.co/npm/nanotimer.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/nanotimer/)\n\nA much higher accuracy timer object that makes use of the node.js [hrtime](http://nodejs.org/api/process.html#process_process_hrtime) function call.\n\nThe nanotimer recreates the internal javascript timing functions with higher resolution.\n\n## Note\n\n- 1) With the normal timing functions, instead of dealing with the obscurities of multiple setTimeout and\nsetInterval calls, now there is a concrete timer object, each of which can handle exactly 1 timeOut and\nsetInterval task. This also means a reference is not needed to clear an interval since each timer object is\nunique.\n\n- 2) Timer objects use the non-blocking feature **setImmediate** for time counting and synchronization. This requires node v0.10.13 or greater\n\n- 3) Errors in timing are non-cumulative.  For example when using the setInterval command, the timer counts\nand compares the time difference since starting against the interval length specified and if it has run past the interval,\nit resets.  If the code had an error of 1 millisecond delay, the timer would actually count to 1001 milliseconds before resetting, and that\n1 millisecond error would propagate through each cycle and add up very quickly!  To solve that problem, rather than resetting\nthe interval variable each cycle, it is instead incremented with each cycle count.  So on the 2nd cycle, it compares to 2000 milliseconds,\nand it may run to 2001.  Then 3000 milliseconds, running to 3001, and so on.  This is only limited by the comparison variable potentially overflowing, so I\nsomewhat arbitrarily chose a value of 8 quadrillion (max is roughly 9 quadrillion in javascript) before it resets.  Even using nanosecond resolution however,\nthe comparison variable would reach 8 quadrillion every 8 million seconds, or every 93.6ish days.\n\n## Usage\n\n```js\n\nvar NanoTimer = require('nanotimer');\n\nvar timerA = new NanoTimer();\n\n\n```\n\nEach nanotimer object can run other functions that are already defined.  This can be done in 2 ways; with either a literal function object, or with a function declaration.\n\n### by function object\n```js\nvar NanoTimer = require('nanotimer');\nvar timerObject = new NanoTimer();\n\n\nvar countToOneBillion = function () {\n    var i = 0;\n    while(i < 1000000000){\n        i++;\n    }\n};\n\nvar microsecs = timerObject.time(countToOneBillion, '', 'u');\nconsole.log(microsecs);\n```\n\nor something like this:\n\n### by function declaration\n\n```js\nvar NanoTimer = require('nanotimer');\n\nfunction main(){\n    var timerObject = new NanoTimer();\n\n    var microsecs = timerObject.time(countToOneBillion, '', 'u');\n    console.log(microsecs);\n}\n\nfunction countToOneBillion(){\n    var i = 0;\n    while(i < 1000000000){\n        i++;\n    }\n}\n\nmain();\n```\n\n## Full example\n\n```js\nvar NanoTimer = require('nanotimer');\n\nvar count = 10;\n\n\nfunction main(){\n    var timer = new NanoTimer();\n\n    timer.setInterval(countDown, '', '1s');\n    timer.setTimeout(liftOff, [timer], '10s');\n\n\n\n}\n\nfunction countDown(){\n    console.log('T - ' + count);\n    count--;\n}\n\nfunction liftOff(timer){\n    timer.clearInterval();\n    console.log('And we have liftoff!');\n}\n\nmain();\n```\n\n### In the example above, the interval can also be cleared another way rather than having to pass in the timer object to the liftOff task.\nInstead, it can be done by specifying a callback to setTimeout, since the timer object will exist in that scope.  Like so:\n\n```js\ntimer.setTimeout(liftOff, '', '10s', function(){\n    timer.clearInterval();\n});\n```\n\n\n## .setTimeout(task, args, timeout, [callback])\n* **task**\n  * The function or task to run.  Can be either a literal function object or reference to a function declaration.\n* **args**\n  * An array of arguments to pass to **task**, or an empty string,  **''** , if there are none.  Note, even a single argument must be passed as an element in an array.\n  * Ex. ['someString', 5, someVariable]\n* **timeout**\n  * The amount of time to wait before calling **task**.   This is a string containing a non-zero integer concatenated with one of 4 possible unit specifiers.\n  * Unit specifiers are:\n    * **s** = seconds\n    * **m** = milliseconds\n    * **u** = microseconds\n    * **n** = nanoseconds\n  * Ex. '500s', '37u', '45n'\n* **[callback]]**\n  * The optional callback function to execute after the timeout has triggered.\n\n\n```js\nconsole.log(\"It's gonna be legen-wait for it...\");\n\ntimerA.setTimeout(dary, '', '2s');\n\nfunction dary(){\n    console.log(\"dary!!\");\n}\n```\n\n## .setInterval(task, args, interval, [callback])\n* **task**\n  * The function or task to run.  Can be either a literal function object or reference to a function declaration.\n* **args**\n  * An array of arguments to pass to **task**, or an empty string,  **''** , if there are none.  Note, even a single argument must be passed as an element in an array.\n  * Ex. ['someString', 5, someVariable]\n* **interval**\n  * The interval of time to wait between each call of **task**.   This is a string containing a non-zero integer concatenated with one of 4 possible unit specifiers.\n  * Unit specifiers are:\n    * **s** = seconds\n    * **m** = milliseconds\n    * **u** = microseconds\n    * **n** = nanoseconds\n  * Ex. '500s', '37u', '45n'\n  * **Note**: \n    * If **interval** is specified as 0, the timer will run **task** as fast as possible.\n    * This function is self correcting, error does not propagate through each cycle, as described above.\n* **[callback]]**\n  * The optional callback function to execute after the timeout has triggered.\n \n```js\ntimerA.setInterval(task, '100m', function(err) {\n    if(err) {\n        //error\n    }\n});\n```\n\n## .time(task, args, format, [callback])\n* **task**\n  * The function or task to run.  Can be either a literal function object or reference to a function declaration.\n* **args**\n  * An array of arguments to pass to **task**, or an empty string,  **''** , if there are none.  Note, even a single argument must be passed as an element in an array.\n  * Ex. ['someString', 5, someVariable]\n* **format**\n  * A single unit specifier indicating the format of the data to be returned.\n  * Unit specifiers:\n    * **s** = seconds\n    * **m** = milliseconds\n    * **u** = microseconds\n    * **n** = nanoseconds\n  * Ex. '500s', '37u', '45n'\n* **[callback]**\n  * The optional callback function to execute after the time call has triggered.\n\n### Synchronous Example:\n```js\n\nvar runtimeSeconds = timerA.time(doMath, '', 'u');\n\nfunction doMath(){\n    //do math\n}\n\n```\n\n### Asynchronous Use:\nTo time something asynchronous, you only need to do these 3 things:\n\n1. create a small wrapper function around the asynchronous task.\n2. make the wrapper function take *callback* as a parameter.\n3. manually call the *callback* parameter inside the callback of the asynchronous task.\n\nIt's essentially a chain of callbacks, which is probably already familiar to you. Here's an example that times how long it takes to read a file.\nSuppose you're using node.js's fs.ReadFile, which is asynchronous, then create a wrapper like so:\n```js\nvar NanoTimer = require('nanotimer');\nvar fs = require('fs');\n\nvar timer = new NanoTimer();\n\n\ntimer.time(loadFile, '', 'u', function(time){\n    console.log(\"It took \" + time + \" microseconds to read that file!\");\n});\n\nfunction loadFile(callback){\n    fs.readFile('testReadFile.js', function(err, data){\n        if(err) throw err;\n        console.log(data);\n\n        callback();\n    });\n}\n```\n\n\n## .clearInterval()\n* Clears current running interval\n```js\ntimer.clearInterval();\n```\n\n## .clearTimeout()\n* Clears current running timeOut\n```js\ntimer.clearTimeout();\n```\n\n## .hasTimeout()\n* Returns true if the timer currently has a scheduled timeout, or false otherwise\n```js\ntimer.hasTimeout();\n```\n\n# Logging\n* Added preliminary logging feature.  If a timer is created by passing in 'log', it will enable verbose logging from the timer, so you can\nfigure out the real amount of time being taken for setTimeout or setInterval\n* Currently only works on setInterval, and displays the 'cycle time', or real interval time to demonstrate how error does not propagate.  This will\nbe further expanded on.\n\n# Tests\n\n* Test suite used is mocha.\n* Tests also require **should**\n* In order for the test to perform properly, the timeout must be altered.\n* I prefer running tests with `mocha -R spec -t 10000`\n\n![](https://raw.github.com/Krb686/nanotimer/master/test/nanotimer_0_2_6_test_partial.png \"Test Results\")\n\n# Performance\n\nVersion 0.3.1 brings about a potentially massive performance boost over previous versions.\n\nPrevious versions used a setImmediate loop running as fast as possible for checking when to execute, inside setTimeout and setInterval.\nIn 0.3.1, this has changed when using an intervalTime (setInterval), or delayTime (setTimeout) that is longer than 25ms.  Execution will be deferred to the standard\njavascript setTimeout, aimed for 25ms before scheduled execution, where the setImmediate loop will resume.\n\nThe assumed error of javascript's setTimeout is 25ms.\n\nBelow is a test case with setInterval set to 1 second.\n\n![](https://raw.github.com/Krb686/nanotimer/master/test/nanotimer_non_deferred.png \"Non-Deferred\")\n\n![](https://raw.github.com/Krb686/nanotimer/master/test/nanotimer_deferred.png \"Deferred\")\n\n\n\n"
  },
  {
    "path": "lib/nanotimer.js",
    "content": "function NanoTimer(log){\n\n\tvar version = process.version;\n\tvar major = version.split('.')[0];\n\tmajor = major.split('v')[1];\n\tvar minor = version.split('.')[1];\n\n\tif ((major == 0) && (minor < 10)){\n\t\tconsole.log('Error: Please update to the latest version of node! This library requires 0.10.x or later');\n\t\tprocess.exit(0);\n\t}\n\n\t//Time reference variables\n\tthis.intervalT1 = null;\n\tthis.timeOutT1 = null;\n\tthis.intervalCount = 1;\n\n\t//Deferred reference indicator variables.  Indicate whether the timer used/will use the deferred call. ie - delay/interval > 25ms\n\tthis.deferredInterval = false;\n\tthis.deferredTimeout = false;\n\n\t//Deferred reference variables.  Used to clear the native js timeOut calls\n\tthis.deferredTimeoutRef = null;\n\tthis.deferredIntervalRef = null;\n\n\t//Callback reference variables.  Used to be able to still successfully call callbacks when timeouts or intervals are cleared.\n\tthis.timeoutCallbackRef = null;\n\tthis.intervalCallbackRef = null;\n\n\t//Immediate reference variables. Used to clear functions scheduled with setImmediate from running in the event timeout/interval is cleared.\n\tthis.timeoutImmediateRef = null;\n\tthis.intervalImmediateRef = null;\n\n\tthis.intervalErrorChecked = false;\n\n\tthis.intervalType = \"\";\n\n\tthis.timeoutTriggered = false;\n\n\tif(log){\n\t\tthis.logging = true;\n\t}\n}\n\nNanoTimer.prototype.time = function(task, args, format, callback){\n\t//Asynchronous task\n\tif(callback){\n\t\tvar t1 = process.hrtime();\n\n\n\t\tif(args){\n\n\t\t\targs.push(function(){\n\t\t\t\tvar time = process.hrtime(t1);\n\t\t\t\tif(format == 's'){\n\t\t\t\t\tcallback(time[0] + time[1]/1000000000);\n\t\t\t\t} else if (format == 'm'){\n\t\t\t\t\tcallback(time[0]*1000 + time[1]/1000000);\n\t\t\t\t} else if (format == 'u'){\n\t\t\t\t\tcallback(time[0]*1000000 + time[1]/1000);\n\t\t\t\t} else if (format == 'n'){\n\t\t\t\t\tcallback(time[0]*1000000000 + time[1]);\n\t\t\t\t} else {\n\t\t\t\t\tcallback(time);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\ttask.apply(null, args);\n\t\t} else {\n\t\t\ttask(function(){\n\t\t\t\tvar time = process.hrtime(t1);\n\t\t\t\tif(format == 's'){\n\t\t\t\t\tcallback(time[0] + time[1]/1000000000);\n\t\t\t\t} else if (format == 'm'){\n\t\t\t\t\tcallback(time[0]*1000 + time[1]/1000000);\n\t\t\t\t} else if (format == 'u'){\n\t\t\t\t\tcallback(time[0]*1000000 + time[1]/1000);\n\t\t\t\t} else if (format == 'n'){\n\t\t\t\t\tcallback(time[0]*1000000000 + time[1]);\n\t\t\t\t} else {\n\t\t\t\t\tcallback(time);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t//Synchronous task\n\t} else {\n\t\tvar t1 = process.hrtime();\n\n\t\tif(args){\n\t\t\ttask.apply(null, args);\n\t\t} else{\n\t\t\ttask();\n\t\t}\n\n\t\tvar t2 = process.hrtime(t1);\n\n\t\tif(format == 's'){\n\t\t\treturn t2[0] + t2[1]/1000000000;\n\t\t} else if (format == 'm'){\n\t\t\treturn t2[0]*1000 + t2[1]/1000000;\n\t\t} else if (format == 'u'){\n\t\t\treturn t2[0]*1000000 + t2[1]/1000;\n\t\t} else if (format == 'n'){\n\t\t\treturn t2[0]*1000000000 + t2[1];\n\t\t} else {\n\t\t\treturn process.hrtime(t1);\n\t\t}\n\t}\n};\n\nNanoTimer.prototype.setInterval = function(task, args, interval, callback){\n\n\tif(!this.intervalErrorChecked){\n\t\t//Task error handling\n\t\tif(!task){\n\t\t\tconsole.log(\"A task function must be specified to setInterval\");\n\t\t\tprocess.exit(1);\n\t\t} else {\n\t\t\tif(typeof(task) != \"function\"){\n\t\t\t\tconsole.log(\"Task argument to setInterval must be a function reference\");\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t}\n\n\t\t//Interval error handling\n\t\tif(!interval){\n\t\t\tconsole.log(\"An interval argument must be specified\");\n\t\t\tprocess.exit(1);\n\t\t} else {\n\t\t\tif(typeof(interval) != \"string\"){\n\t\t\t\tconsole.log(\"Interval argument to setInterval must be a string specified as an integer followed by 's' for seconds, 'm' for milli, 'u' for micro, and 'n' for nanoseconds. Ex. 2u\");\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t}\n\n\t\t//This ref is used if deferred timeout is cleared, so the callback can still be accessed\n\t\tif(callback){\n\t\t\tif(typeof(callback) != \"function\"){\n\t\t\t\tconsole.log(\"Callback argument to setInterval must be a function reference\");\n\t\t\t\tprocess.exit(1);\n\t\t\t} else {\n\t\t\t\tthis.intervalCallbackRef = callback;\n\t\t\t}\n\t\t}\n\n\t\tthis.intervalType = interval[interval.length-1];\n\n\t\tif(this.intervalType == 's'){\n\t\t\tthis.intervalTime = interval.slice(0, interval.length-1) * 1000000000;\n\t\t} else if(this.intervalType == 'm'){\n\t\t\tthis.intervalTime = interval.slice(0, interval.length-1) * 1000000;\n\t\t} else if(this.intervalType == 'u'){\n\t\t\tthis.intervalTime = interval.slice(0, interval.length-1) * 1000;\n\t\t} else if(this.intervalType == 'n'){\n\t\t\tthis.intervalTime = interval.slice(0, interval.length-1);\n\t\t} else {\n\t\t\tconsole.log('Error with argument: ' + interval + ': Incorrect interval format. Format is an integer followed by \"s\" for seconds, \"m\" for milli, \"u\" for micro, and \"n\" for nanoseconds. Ex. 2u');\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tthis.intervalErrorChecked = true;\n\t}\n\n\n\n\t//Avoid dereferencing inside of function objects later\n\t//Must be performed on every execution \n\tvar thisTimer = this;\n\n\tif(this.intervalTime > 0){\n\n\t\t//Check and set constant t1 value.\n\t\tif(this.intervalT1 == null){\n\t\t\tthis.intervalT1 = process.hrtime();\n\t\t}\n\n\t\t//Check for overflow.  Every 8,000,000 seconds (92.6 days), this will overflow\n\t\t//and the reference time T1 will be re-acquired.  This is the only case in which error will \n\t\t//propagate.\n\t\tif(this.intervalTime*this.intervalCount > 8000000000000000){\n\t\t\tthis.intervalT1 = process.hrtime();\n\t\t\tthis.intervalCount = 1;\n\t\t}\n\n\n\t\t//Get comparison time\n\t\tthis.difArray = process.hrtime(this.intervalT1);\n\t\tthis.difTime = (this.difArray[0] * 1000000000) + this.difArray[1];\n\n\t\t//If updated time < expected time, continue\n\t\t//Otherwise, run task and update counter\n\t\tif(this.difTime < (this.intervalTime*this.intervalCount)){\n\n\t\t\t//Can potentially defer to less accurate setTimeout if intervaltime > 25ms\n\t\t\tif(this.intervalTime > 25000000){\n\t\t\t\tif(this.deferredInterval == false){\n\t\t\t\t\tthis.deferredInterval = true;\n\t\t\t\t\tvar msDelay = (this.intervalTime - 25000000) / 1000000.0;\n\t\t\t\t\tthis.deferredIntervalRef = setTimeout(function(){thisTimer.setInterval(task, args, interval, callback);}, msDelay);\n\t\t\t\t} else {\n\t\t\t\t\tthis.deferredIntervalRef = null;\n\t\t\t\t\tthis.intervalImmediateRef = setImmediate(function(){thisTimer.setInterval(task, args, interval, callback);});\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.intervalImmediateRef = setImmediate(function(){thisTimer.setInterval(task, args, interval, callback);});\n\t\t\t}\n\t\t} else {\n\n\t\t\tthis.intervalImmediateRef = null;\n\n\t\t\tif(this.logging){\n\t\t\t\tconsole.log('nanotimer log: ' + 'cycle time at - ' + this.difTime);\n\t\t\t}\n\n\n\t\t\tif(args){\n\t\t\t\ttask.apply(null, args);\n\t\t\t} else {\n\t\t\t\ttask();\n\t\t\t}\n\n\t\t\t//Check if the intervalT1 is still not NULL. If it is, that means the task cleared the interval so it should not run again.\n\t\t\tif(this.intervalT1){\n\t\t\t\tthis.intervalCount++;\n\t\t\t\tthis.deferredInterval = false;\n\t\t\t\tthis.intervalImmediateRef = setImmediate(function(){thisTimer.setInterval(task, args, interval, callback);});\n\t\t\t}\n\t\t}\n\n\t//If interval = 0, run as fast as possible.\n\t} else {\n\n\t\t//Check and set constant t1 value.\n\t\tif(this.intervalT1 == null){\n\t\t\tthis.intervalT1 = process.hrtime();\n\t\t}\n\n\t\tif(args){\n\t\t\ttask.apply(null, args);\n\t\t} else {\n\t\t\ttask();\n\t\t}\n\n\t\t// This needs to be re-checked here incase calling task turned this off\n\t\tif(this.intervalT1){\n\t\t\tthis.intervalImmediateRef = setImmediate(function(){thisTimer.setInterval(task, args, interval, callback);});\n\t\t}\n\t}\n};\n\nNanoTimer.prototype.setTimeout = function(task, args, delay, callback){\n\n\t//Task error handling\n\tif(!task){\n\t\tconsole.log(\"A task function must be specified to setTimeout\");\n\t\tprocess.exit(1);\n\t} else {\n\t\tif(typeof(task) != \"function\"){\n\t\t\tconsole.log(\"Task argument to setTimeout must be a function reference\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t}\n\n\t//Delay error handling\n\tif(!delay){\n\t\tconsole.log(\"A delay argument must be specified\");\n\t\tprocess.exit(1);\n\t} else {\n\t\tif(typeof(delay) != \"string\"){\n\t\t\tconsole.log(\"Delay argument to setTimeout must be a string specified as an integer followed by 's' for seconds, 'm' for milli, 'u' for micro, and 'n' for nanoseconds. Ex. 2u\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t}\n\n\t//This ref is used if deferred timeout is cleared, so the callback can still be accessed\n\tif(callback){\n\t\tif(typeof(callback) != \"function\"){\n\t\t\tconsole.log(\"Callback argument to setTimeout must be a function reference\");\n\t\t\tprocess.exit(1);\n\t\t} else {\n\t\t\tthis.timeoutCallbackRef = callback;\n\t\t}\n\t}\n\n\t//Avoid dereferencing\n\tvar thisTimer = this;\n\n\tif(this.timeoutTriggered){\n\t\tthis.timeoutTriggered = false;\n\t}\n\n\tvar delayType = delay[delay.length-1];\n\n\tif(delayType == 's'){\n\t\tvar delayTime = delay.slice(0, delay.length-1) * 1000000000;\n\t} else if(delayType == 'm'){\n\t\tvar delayTime = delay.slice(0, delay.length-1) * 1000000;\n\t} else if(delayType == 'u'){\n\t\tvar delayTime = delay.slice(0, delay.length-1) * 1000;\n\t} else if(delayType == 'n'){\n\t\tvar delayTime = delay.slice(0, delay.length-1);\n\t} else {\n\t\tconsole.log('Error with argument: ' + delay + ': Incorrect delay format. Format is an integer followed by \"s\" for seconds, \"m\" for milli, \"u\" for micro, and \"n\" for nanoseconds. Ex. 2u');\n\t\tprocess.exit(1);\n\t}\n\n\t//Set marker\n\tif(this.timeOutT1 == null){\n\t\tthis.timeOutT1 = process.hrtime();\n\t}\n\n\n\tvar difArray = process.hrtime(this.timeOutT1);\n\tvar difTime = (difArray[0] * 1000000000) + difArray[1];\n\n\n\tif(difTime < delayTime){\n\t\t//Can potentially defer to less accurate setTimeout if delayTime > 25ms\n\t\tif(delayTime > 25000000){\n\t\t\tif(this.deferredTimeout == false){\n\t\t\t\tthis.deferredTimeout = true;\n\t\t\t\tvar msDelay = (delayTime - 25000000) / 1000000.0;\n\t\t\t\tthis.deferredTimeoutRef = setTimeout(function(){thisTimer.setTimeout(task, args, delay, callback);}, msDelay);\n\t\t\t} else {\n\t\t\t\tthis.deferredTimeoutRef = null;\n\t\t\t\tthis.timeoutImmediateRef = setImmediate(function(){thisTimer.setTimeout(task, args, delay, callback);});\n\t\t\t}\n\t\t} else {\n\t\t\tthis.timeoutImmediateRef = setImmediate(function(){thisTimer.setTimeout(task, args, delay, callback);});\n\t\t}\n\t} else {\n\t\tthis.timeoutTriggered = true;\n\t\tthis.timeoutImmediateRef = null;\n\t\tthis.timeOutT1 = null;\n\t\tthis.deferredTimeout = false;\n\n\t\tif(this.logging == true){\n\t\t\tconsole.log('nanotimer log: ' + 'actual wait - ' + difTime);\n\t\t}\n\n\t\tif(args){\n\t\t\ttask.apply(null, args);\n\t\t} else{\n\t\t\ttask();\n\t\t}\n\n\t\tif(callback){\n\t\t\tvar data = {'waitTime':difTime};\n\t\t\tcallback(data);\n\t\t}\n\n\t}\n};\n\nNanoTimer.prototype.clearInterval = function(){\n\n\n\tif(this.deferredIntervalRef){\n\t\tclearTimeout(this.deferredIntervalRef);\n\n\t\tthis.deferredInterval = false;\n\t}\n\n\tif(this.intervalImmediateRef){\n\t\tclearImmediate(this.intervalImmediateRef);\n\t}\n\n\tthis.intervalT1 = null;\n\tthis.intervalCount = 1;\n\tthis.intervalErrorChecked = false;\n\n\n\tif(this.intervalCallbackRef){\n\t\tthis.intervalCallbackRef();\n\t}\n\n};\n\nNanoTimer.prototype.clearTimeout = function(){\n\n\t// Only do something if this is not being called as a result\n\t// of the timeout triggering\n\tif(this.timeoutTriggered == false){\n\t\tif(this.deferredTimeoutRef){\n\t\t\tclearTimeout(this.deferredTimeoutRef);\n\n\t\t\tif(this.timeOutT1) {\n\t\t\t\tvar difArray = process.hrtime(this.timeOutT1);\n\t\t\t\tvar difTime = (difArray[0] * 1000000000) + difArray[1];\n\t\t\t}\n\n\t\t\tthis.deferredTimeout = false;\n\t\t}\n\n\t\tif(this.timeoutImmediateRef){\n\t\t\tclearImmediate(this.timeoutImmediateRef);\n\t\t}\n\n\t\tthis.timeOutT1 = null;\n\n\t\tif(this.timeoutCallbackRef){\n\t\t\tvar data = {'waitTime':difTime};\n\t\t\tthis.timeoutCallbackRef(data);\n\t\t}\n\t}\n};\n\nNanoTimer.prototype.hasTimeout = function(){\n\treturn this.timeOutT1 != null;\n};\n\nmodule.exports = NanoTimer;\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"nanotimer\",\n  \"main\": \"./lib/nanotimer.js\",\n  \"description\": \"A much higher accuracy timer object that makes use of the node.js hrtime function call.\",\n  \"version\": \"0.3.15\",\n  \"authors\": [\n    \"Kevin Briggs <krb686@gmail.com> (https://github.com/Krb686)\"\n  ],\n  \"keywords\": [\n    \"timer\",\n    \"nanotimer\",\n    \"nano\",\n    \"nanoseconds\",\n    \"micro\",\n    \"microseconds\",\n    \"stopwatch\"\n  ],\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/Krb686/nanotimer.git\"\n  },\n  \"devDependencies\": {\n    \"mocha\": \"^2.3.4\",\n    \"should\": \"^7.1.1\"\n  },\n  \"scripts\": {\n    \"test\": \"mocha\"\n  },\n  \"license\": \"ISC\"\n}\n"
  },
  {
    "path": "test/test-nanotimer.js",
    "content": "var NanoTimer = require('../lib/nanotimer.js');\nvar should = require('should');\n\nvar timerA = new NanoTimer('log');\n\n\ndescribe('nanoTimer', function(){\n    this.timeout(60 * 1000);\n\n    //######## time function #########\n    describe('.time', function(){\n        \n        //Test 1 - Synchronous Task Timing\n        it('#1: synchronous, count to 1 million, 1000 samples', function(){\n            \n            var times = [];\n            var i = 0;\n            var numSamples = 1000;\n            \n            //Simple count to 1 million task\n            var syncTask = function(){\n                var count = 0;\n                var i = 0;\n                for(i=0;i<1000000;i++){\n                    count++;\n                };\n            };\n            \n            //Test numSamples # of times\n            for(i=0;i<numSamples;i++){\n                times.push(timerA.time(syncTask, [], 'm'));\n            }\n            \n            //Assertions\n            times.length.should.eql(1000);\n            \n            var avg = 0;\n            var max = 0;\n            var min = 1000000000000000000;\n            for(i=0;i<numSamples;i++){\n                avg+=times[i];\n                if(times[i] > max){\n                    max = times[i];\n                }\n                \n                if(times[i] < min){\n                    min = times[i];\n                }\n            }\n            \n            avg = avg/numSamples;\n            console.log('\\n\\t\\t - Average time: ' + avg + ' milliseconds');\n            console.log('\\t\\t - Max time: ' + max + ' milliseconds');\n            console.log('\\t\\t - Min time: ' + min + ' milliseconds');\n            \n        });\n        \n        //Test 2 - Asynchronous Task Timing\n        it('#2: asynchronous, count to 1 million, 1000 samples', function(done){\n            \n            var i = 0;\n            var j = 0;\n            var numSamples = 1000;\n            var doneCount = 0;\n            var times = [];\n            \n            //Count to 1000 asynchronously\n            var asyncTask = function(callback){\n                \n                if(i < 1000000){\n                    setImmediate(function(){asyncTask(callback);});\n                } else {\n                    callback();\n                }\n                \n                i++;\n            };\n            \n            //Run 10 instances of async task.\n            for(j=0;j<numSamples;j++){\n                timerA.time(asyncTask, [], 's', function(runtime){\n                    should.exist(runtime);\n                    times.push(runtime);\n                    doneCount++;\n                    if(doneCount == numSamples){\n                        var avg = 0;\n                        var max = 0;\n                        var min = 1000000000000000000;\n                        for(i=0;i<1000;i++){\n                            avg+=times[i];\n                            if(times[i] > max){\n                                max = times[i];\n                            }\n                \n                            if(times[i] < min){\n                                min = times[i];\n                            }\n                        }\n            \n                        avg = avg/numSamples;\n                        console.log('\\n\\t\\t - Average time: ' + avg + ' seconds');\n                        console.log('\\t\\t - Max time: ' + max + ' seconds');\n                        console.log('\\t\\t - Min time: ' + min + ' seconds');\n                        done(); \n                    }\n                });\n            } \n        });\n\n        it('#3: asnyc - make sure callback format is correct', function(done) {\n            timerA.time(function methodReturningAfterApprox2000ms(callback) {\n                setTimeout(callback, 2000);\n            }, '', 'm', function resultCallback(timeTakenInMs) {\n                timeTakenInMs.should.be.within(1900, 2100);\n\t\t\t\tconsole.log('\\t\\t - Time taken should be between 1900-2100 ms');\n\t\t\t\tconsole.log('\\t\\t - Time taken: ' + timeTakenInMs);\n                done();\n            });\n        });\n    });\n    \n    \n    //######## timeout function ########\n    describe('.setTimeout && clearTimeout', function(){\n        //Test 4 - sync task\n        it('#4: sync, wait 0.1 seconds, 20 samples\\n\\n', function(done){\n            var i = 0;\n            var j = 0;\n            var numSamples = 20;\n            var doneCount = 0;\n            var errors = [];\n            var minError = 1000000000;\n            var maxError = 0;\n            var avgError = 0;\n            \n            \n            var task = function(){\n                var count = 0;\n                for(i=0;i<1000000;i++){\n                    count++;\n                }; \n            };\n            \n            for(j=0;j<numSamples;j++){\n                \n                timerA.setTimeout(task, [], '0.1s', function(data){\n                    var waitTime = data.waitTime;\n                    console.log('\\t\\t - Sample #' + (doneCount+1));\n                    console.log('\\t\\t\\t - Expected wait: 0.1 seconds');\n                    console.log('\\t\\t\\t - Actual wait: ' + waitTime/1000000000 + ' seconds');\n                    var error = (((waitTime - 100000000) / (100000000)) * 100);\n                    console.log('\\t\\t\\t - Error: ' + error + '%');\n                    errors.push(error);\n                    var waitedLongEnough = (waitTime >= 100000000);\n                    waitedLongEnough.should.be.true;\n                    \n                    doneCount++;\n                    \n                    if(doneCount == numSamples){\n                        for(i=0;i<numSamples;i++){\n                            if(errors[i] < minError){\n                                minError = errors[i];\n                            }\n                            \n                            if (errors[i] > maxError){\n                                maxError = errors[i];\n                            }\n                            \n                            avgError += errors[i];\n                        }\n                        avgError = avgError / numSamples;\n                        console.log('\\t\\t - Min. Error: ' + minError + '%');\n                        console.log('\\t\\t - Max. Error: ' + maxError + '%');\n                        console.log('\\t\\t - Avg. Error: ' + avgError + '%');\n                        done();\n                    }\n                });\n            }\n            \n            \n            \n        });\n        \n        //Test 5 - async task\n        it('#5: setTimeout on async function with callback\\n\\n', function(done){\n            var asyncTask = function(callback, i){\n                if(!i){\n                    var i = 0;\n                }\n                \n                if(i < 1000){\n                    setImmediate(function(){\n                        i++;\n                        asyncTask(callback, i);\n                    });\n                } else {\n                    callback('got data');\n                }\n            };\n            \n            var runAsync = function(){\n                var msg = '';\n                asyncTask(function(data){\n                    msg = data;\n                    msg.should.eql('got data');\n                });  \n            };\n            \n            timerA.setTimeout(runAsync, [], '1s', function(data) {\n                var waitTime = data.waitTime;\n                console.log('\\t\\t - Expected wait: 1 seconds');\n                console.log('\\t\\t - Actual wait: ' + waitTime/1000000000 + ' seconds');\n                console.log('\\t\\t - Error: ' + (((waitTime - 1000000000) / (1000000000)) * 100) + '%');\n                var waitedLongEnough = (waitTime >= 1000000000);\n                waitedLongEnough.should.be.true;\n                done();\n            });\n            \n        });\n        \n        //Test #6 - timeout with args passed\n        it('#6 works with functions with args passed in\\n\\n', function(done){\n            var someObject = {};\n            someObject.number = 10;\n        \n        \n            var taskWithArgs = function(object){\n                object.number = 5;\n            };\n            \n            timerA.setTimeout(taskWithArgs, [someObject], '1s', function(data){\n                var waitTime = data.waitTime;\n                console.log('\\t\\t - Expected wait: 1 seconds');\n                console.log('\\t\\t - Actual wait: ' + waitTime/1000000000 + ' seconds');\n                console.log('\\t\\t - Error: ' + (((waitTime - 1000000000) / (1000000000)) * 100) + '%');\n                var waitedLongEnough = (waitTime >= 1000000000);\n                waitedLongEnough.should.be.true;\n                someObject.number.should.eql(5);\n                done();\n            \n            });\n            \n            \n        });\n\t\t\n\t\t//Test #7 - clearTimeout works\n\t\tit('#7 clearTimeout before task is run - works\\n\\n', function(done){\n\t\t\n\t\t\n\t\t\tvar value = 0;\n\t\t\t\n\t\t\tvar task = function(){\n\t\t\t\tconsole.log('\\t\\t #6 task was run!');\n\t\t\t\tvalue++;\n\t\t\t};\n\t\t\t\n\t\t\ttimerA.setTimeout(task, [], '1s', function(data){\n\t\t\t\tvar waitTime = data.waitTime;\n\t\t\t\tconsole.log('\\t\\t - Expected wait: 1 second');\n\t\t\t\tconsole.log('\\t\\t - Actual wait: ' + waitTime/1000000000 + ' seconds');\n\t\t\t\tvar waitedShortEnough = (waitTime < 1000000000);\n\t\t\t\twaitedShortEnough.should.be.true;\n\t\t\t\tvalue.should.eql(0);\n\t\t\t\tdone();\n\t\t\t});\n\t\t\t\n\t\t\ttimerA.clearTimeout();\n\t\t\t\n\t\t});\n\t\t\n\t\t\n        \n    });\n    \n    //######## setInterval function ########\n    describe('setInterval && clearInterval', function(){\n\t\n\t\t//Test #8 - setInterval works\n        it('#8 successfully works\\n\\n', function(done){\n        \n            var task = function(){\n                console.log('\\t\\t - task was run!');\n            };\n            \n            \n            timerA.setInterval(task, [], '0.1s', function(){\n                done();\n            });\n            \n            timerA.setTimeout(function(){\n                console.log('\\t\\t - clearing interval');\n                timerA.clearInterval();\n            }, [], '5s');\n\n        });\n\n\t\tit('#9 setInterval with interval = 0: incrementing a variable as fast as possible.', function(done){\n\n\t\t\tvar i=0;\n\t\t\tvar taskCount = 0;\n\n\t\t\tvar task = function(){\n\t\t\t\ti++;\n\t\t\t}\n\n\t\t\tvar launchTask = function(){\n\t\t\t\tconsole.log(\"Task is being launched!\");\n\t\t\t\ttimerA.setInterval(task, [], '0s', function(){\n\t\t\t\t\tconsole.log(\"Task count = \" + taskCount);\n\t\t\t\t\tif(taskCount < 10){\n\t\t\t\t\t\tconsole.log(\"relaunching\");\n\t\t\t\t\t\ttaskCount++;\n\t\t\t\t\t\tconsole.log(\"i = \" + i);\n\t\t\t\t\t\ti = 0;\n\t\t\t\t\t\tlaunchTask();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconsole.log(\"Test #8 done!\")\n\t\t\t\t\t\tdone();\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tconsole.log(\"T8 - setting timeout\");\n\t\t\t\ttimerA.setTimeout(function(){\n\t\t\t\t\tconsole.log('\\t\\t T8 - clearing interval');\n\t\t\t\t\ttimerA.clearInterval();\n\t\t\t\t}, [], '0.2s');\n\t\t\t}\n\n\t\t\tconsole.log(\"starting the initial task\");\n\t\t\t// Trigger the first launch\n\t\t\tlaunchTask();\n\n\t\t});\n\n\t\tit('#10 setInterval - clearing interval from within the task, non-zero timeout', function(done){\n\n\t\t\t\n\t\t\tconsole.log(\"Starting test #9\");\n\t\t\tconsole.log(\"Clearing the interval from the task, zon-zero timeout\");\n\t\t\t\t\n\t\t\tvar task = function(){\n\t\t\t\tconsole.log(\"Running some task!\");\n\t\t\t\tvar i = 0;\n\t\t\t\twhile(i<100){\n\t\t\t\t\ti++;\n\t\t\t\t}\n\t\t\t\tconsole.log(\"Clearing the interval\");\n\t\t\t\ttimerA.clearInterval();\n\t\t\t};\n\n\t\t\ttimerA.setInterval(task, [], '1s', function(){\n\t\t\t\tconsole.log(\"Test #9 done!\");\n\t\t\t\tdone();\n\n\n\t\t\t});\n\t\t});\n\n\t\tit('#11 setInterval - clearing the interval from within the task, zero timeout', function(done){\n\n\t\t\tconsole.log(\"Starting test #10\");\n\t\t\tconsole.log(\"Clearing the interval from the task, zero timeout\");\n\t\t\tvar i=0;\n\t\t\tvar task = function(){\n\t\t\t\tif(i < 10){\n\t\t\t\t\tconsole.log(\"i = \" + i);\n\t\t\t\t\ti++;\n\t\t\t\t} else {\n\t\t\t\t\ttimerA.clearInterval();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\ttimerA.setInterval(task, [], '0s', function(){\n\t\t\t\tdone();\n\t\t\t});\n\n\t\t});\n        \n    });\n    \n});\n\n\n\n\n"
  }
]