nodemcu / nodemcu-firmware

Lua based interactive firmware for ESP8266, ESP8285 and ESP32
https://nodemcu.readthedocs.io
MIT License
7.66k stars 3.12k forks source link

Named timers #963

Closed dvv closed 8 years ago

dvv commented 8 years ago

Hi!

I would like I could use named timers:

tmr.alarm("foo", 1000, 0, function() print("foo fired") end)

The rationale is not to bother with numbers which are subject for clashes in systems consisting of modules (timer ids should be kept in developer's memory). To cope with the problem one might use big numbers (harder to clash) but I believe it will occupy fruitlessly memory in timers array (did not check):

{[1]=timer1, --[[ _gap_, ]][1000]=timer1000}

instead of

{foo=timer1, bar=timer1000}

If subj is not feasible, how do I reliably mimick anonymous timers like JavaScript's setTimeout(fun, after)?

TIA --Vladimir

TerryE commented 8 years ago

@dvv, Vladimir we've discussed this before, though I haven't checked if the issue is still open but IMO the best way to provide this flexibility would be to allow an OO model:

  my_alarm = tmr.new()
  my_alarm:alarm("foo", 1000, function() print("foo fired") end)

But there are issues relating to backwards compatibility, minimising resource leakage, garbage collection, etc. that we would need to be really careful with. A nice to have, but not high on my priorities at the moment.

dvv commented 8 years ago

I see. Right, idea is clear and I can try to mimick timer allocation at Lua level.

dvv commented 8 years ago

Kinda this:

do
  local timers = {}
  local new = function(timeout, repeating, handler, ...)
    local a = {...}
    local n = #timers + 1
    tmr.alarm(n, timeout, 1, function()
      handler(unpack(a))
    end)
    -- TODO: names?
    timers[n] = n
    return n
  end
  -- NB: globals!
  setInterval = function(timeout, handler, ...)
    return new(timeout, 1, handler, ...)
  end
  clearInterval = function(n)
    tmr.unregister(n)
    timers[n] = nil
  end
  setTimeout = function(timeout, handler, ...)
    return new(timeout, 0, handler, ...)
  end
  clearTimeout = clearInterval
end
TerryE commented 8 years ago

You are deleting entries in timers so it sparse and therefore #timers is a little flaky. You should scan for the first timer < 7 returning nil. Remember that timers are numbered using the C convention not the Lua one, that is 0..6 not 1..7. I've been tripped up myself on this one.

I am up to my eyes in work at the moment, so haven't been able to review properly. Sorry, but this is also a #719 issue anyway :smile:

dvv commented 8 years ago

#t will always stop at first nil found. That is the point and is shortcut for scanning. And I reserved 0 as untouchable, for system purpose, yes.

Oh, nothing offending the frozen state, it's pure lua workaround.

Though I personally would like to have in the C core unlimited number of anonymous timers implemented in software using one/two hardware timers. Just like they try to do in more constrained systems.

nickandrew commented 8 years ago

Though I personally would like to have in the C core unlimited number of anonymous timers implemented in software using one/two hardware timers. Just like they try to do in more constrained systems.

:+1: Well the C core has an unlimited number of anonymous timers, it's just the Lua module that pigeonholes it to 7 and a bad API that doesn't allow code to choose an unused timer.