How are the timeout IDs allocated?

Posted on
  • Could someone please explain me how are the IDs allocated? Or even better why it's not like I thought? :)

    In this code below I would expect the ledTimer to get the same value (ID) over and over again but that doesn't happen.

    var btnPin = BTN;
    var ledPin = LED1;
    var ledTimer = null;
    digitalWrite(ledPin, 0);
    
    var btnWatcher = setWatch(function () {
      if (ledTimer) {
        clearTimeout(ledTimer);
        ledTimer = null;
      }
      digitalWrite(ledPin, 1);
      console.log("before: " + ledTimer);
      ledTimer = setTimeout(function () {
        digitalWrite(ledPin, 0);
        ledTimer = null;
      }, 4000);
      console.log("after: " + ledTimer);
    }, btnPin, {repeat: true, edge: "rising", debounce: 70});
    

    Now when I press the button every 5 seconds I get what I expected:

    before: null
    after: 2
    before: null
    after: 2
    ...and so on
    

    But when I press the button every 3 seconds then it's not what I expected:

    before: null
    after: 2
    before: null
    after: 4
    ...and +2 every time
    
  • I'm not sure. I had thought the assignment was:

    • If no timers, assign '1'
    • If there are timers, assign 1 more than the last timer

    However I had to write some code to cope with timers being added/removed while handling a timer, and it could be that does some strange things with the numbering...

  • OK so what is the maximum ID this function can return? Is it some huge number in tens of thousands?

  • Turns out setWatch and setTimeout IDs are shared so that's where value 2 is coming from (watch ID is 1).

    If I add another watch for btnPin (falling) then the timeout ID has value 3 and it's growing +3 every time. That means the ID's value can grow very fast if I have a bunch of timers/watches that I want to add or remove dynamically.

    And that's just the ID's value growing, the number of timers is the same as far as I understand.

  • The ID can be up to 18446744073709551615 - so I think you're safe! That may change to 4294967296 at some point in the future, but even so I think you'll be fine!

  • Lol now that's reassuring.

  • One more question because this is driving me nuts and I can't find the reason why ledTimer gets incremented at all.

    What happens when I clearTimeout(ledTimer) ? Is it set to an empty function so that when it comes to the given time it does nothing, or is it really removed?

    Also when I add console.log(process.memory()); at the beginning of watch function then it shows memory usage goes up quite a lot when I press the button before the timeout passed.

    The output now looks like that:

    {"free":1722,"usage":78,"total":1800,"history":44,"stackEndAddress":536909512,"flash_start":134217728,"flash_binary_end":134432224,"flash_code_start":134443008,"flash_length":262144}
    before: null
    after: 2
    {"free":1695,"usage":105,"total":1800,"history":44,"stackEndAddress":536909512,"flash_start":134217728,"flash_binary_end":134432224,"flash_code_start":134443008,"flash_length":262144}
    before: null
    after: 4
    {"free":1695,"usage":105,"total":1800,"history":44,"stackEndAddress":536909512,"flash_start":134217728,"flash_binary_end":134432224,"flash_code_start":134443008,"flash_length":262144}
    before: null
    after: 6
    > 
    
  • When you say clearTimeout(ledTimer) it should totally remove that timeout and free any memory used by it.

    Surely the increased memory usage is because there is already a timer allocated, as you hadn't yet freed it with clearTimeout?

  • as you hadn't yet freed it with clearTimeout?

    And this is that part that I don't understand :) I AM doing clearTimeout and led behaves like it was removed (timeout is reset) but memory usage and ID numbering suggests otherwise.

  • Surely you're just dumping the memory usage before you remove the timer?

    var btnPin = BTN;
    var ledPin = LED1;
    var ledTimer = null;
    digitalWrite(ledPin, 0);
    var btnWatcher = setWatch(function () {
      console.log("--" + process.memory().usage); // <------------------------------
      if (ledTimer) {
        clearTimeout(ledTimer);
        ledTimer = null;
      }
      digitalWrite(ledPin, 1);
      console.log("before: " + ledTimer);
      ledTimer = setTimeout(function () {
        digitalWrite(ledPin, 0);
        ledTimer = null;
      }, 4000);
      console.log("after: " + ledTimer);
    }, btnPin, {repeat: true, edge: "rising", debounce: 70});
    
    --79
    before: null
    after: 2
    --106
    before: null
    after: 4
    --107
    before: null
    after: 6
    --107
    before: null
    after: 8
    

    Try this:

    var btnPin = BTN;
    var ledPin = LED1;
    var ledTimer = null;
    digitalWrite(ledPin, 0);
    var btnWatcher = setWatch(function () {  
      if (ledTimer) {
        clearTimeout(ledTimer);
        ledTimer = null;
      }
      console.log("--" + process.memory().usage); // <------------------------------
      digitalWrite(ledPin, 1);
      console.log("before: " + ledTimer);
      ledTimer = setTimeout(function () {
        digitalWrite(ledPin, 0);
        ledTimer = null;
      }, 4000);
      console.log("after: " + ledTimer);
    }, btnPin, {repeat: true, edge: "rising", debounce: 70});
    
    --79
    before: null
    after: 2
    --80
    before: null
    after: 4
    --80
    before: null
    after: 6
    --80
    before: null
    after: 8
    --80
    before: null
    after: 10
    
  • Surely you're just dumping the memory usage before you remove the timer?

    Ahhh good catch, thanks! But it was also before I add another timer..

    EDIT: That's it! On the first console.log the memory usage was lower because timer was not even set at this point. Then on the second console.log the timer was finally set and memory usage was higher. Thanks for helping me understand this :)

    Now it's only the ID numbering that puzzles me.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

How are the timeout IDs allocated?

Posted by Avatar for graf @graf

Actions