Skip to content

Latest commit

 

History

History
370 lines (189 loc) · 15.1 KB

hm.timer.md

File metadata and controls

370 lines (189 loc) · 15.1 KB

Module hm.timer

API CHANGE: All timers are of the 'delayed' sort for maximum flexibility.

INTERNAL CHANGE: Don't bother with NSTimer intermediates, we abstract directly from CFRunLoopTimer

Schedule asynchronous execution of functions in the future.

Overview


Module hm.timer

Extends <hm#module>

Function hm.timer.absoluteTime() -> <#number>

Returns the number of seconds since an arbitrary point in the distant past.

  • Returns <#number>: number of seconds, with millisecond precision or better

This function should only be used for measuring time intervals. The starting point is Jan 1 2001 00:00:00 GMT, so not the UNIX epoch.

Function hm.timer.localTime() -> <#number>

INTERNAL CHANGE: high precision

Returns the number of seconds since midnight local time.

  • Returns <#number>: number of seconds, with millisecond precision or better

Function hm.timer.new(fn,data) -> <#timer>

API CHANGE: All hs.timer constructors are covered by the new :run...() methods

Creates a new timer.

  • fn: <#timerFunction> (optional) a function to be executed later

  • data: <?> (optional) arbitrary data that will be passed to fn; as a convenience, you can use the special string "timer" to have fn receive the timer object being created

  • Returns <#timer>: a new timer object

If fn is not provided here, it must be set via timer:setFn() before calling any of the :run...() methods. data can be overridden (and dynamically changed) later when calling the :run...() methods.

Function hm.timer.sleep(s)

Halts all processing for a given interval.

  • s: <#number> interval in seconds

WARNING: this function will stop all processing by Hammermoon. For anything other than very short intervals, use hm.timer.new() with a callback instead.

Function hm.timer.toSeconds(timeString) -> <#number>

Converts to number of seconds


Class timer

Extends <hm#module.object>

Type for timer objects.

A timer holds an execution unit that can be scheduled for running later in time in various ways via its :run...() methods. After being scheduled a timer can be unscheduled (thus prevented from running) via its :cancel() method.

Property (read-only) <#timer>.elapsed: <#number>

API CHANGE: Was <#hs.timer>:nextTrigger() when negative, but only if the timer was not running.

The timer's last execution time, in seconds since.

If the timer has never been executed, this value is the time since creation.

Property <#timer>.nextRun: <#number>

API CHANGE: <#hs.timer>:nextTrigger(), with some differences.

The timer's scheduled next execution time, in seconds from now.

If this value is nil, the timer is currently unscheduled. You cannot set this value to a negative number; setting it to 0 triggers timer execution right away; setting it to nil unschedules the timer.

Property <#timer>.scheduled: <#boolean>

API CHANGE: <#hs.timer>:running(), with some differences.

true if the timer is scheduled for execution.

Setting this to false or nil unschedules the timer.

Method <#timer>:cancel()

API CHANGE: All timers can be rescheduled freely

Unschedule a timer.

The timer's <#timerFunction> will not be executed again until you call one of its :run...() methods.

Method <#timer>:run()

Executes the timer now.

Method <#timer>:runAfter(predicateFn,checkInterval,continueOnError,data)

API CHANGE: Replaces hs.timer.waitWhile() and hs.timer.waitUntil()

Schedules execution of the timer after a given predicate becomes false.

  • predicateFn: <#predicateFunction> A predicate function that determines whether to contine waiting before executing the timer
  • checkInterval: <#intervalString> interval between predicate checks
  • continueOnError: <#boolean> (optional) if true, predicateFn will keep being checked even if it causes an error
  • data: <?> (optional) arbitrary data that will be passed to the <#predicateFunction> and <#timerFunction>

The given predicateFn will start being checked right away. As soon as it returns false, the timer will execute (once).

Method <#timer>:runEvery(repeatInterval,delayOrStartTime,continueOnError,data)

API CHANGE: This replaces all repeating timers, whether created via hs.timer.new(), hs.timer.doEvery(), or hs.timer.doAt()

INTERNAL CHANGE: High frequency timers (less than 1s repeat interval) are like hs.timers, i.e. the repeat schedule is managed internally by the CFRunLoopTimer for performance. Other timers behave like hs.timer.delayeds, i.e. they are rescheduled "manually" after every trigger.

Schedules repeated execution of the timer.

  • repeatInterval: <#intervalString>
  • delayOrStartTime: <?> (optional) the timer will start executing: if omitted or nil, right away; if an <#intervalString> or a number (in seconds), after the given delay; if a <#timeOfDayString>, at the earliest occurrence for the given time
  • continueOnError: <#boolean> (optional) if true, the timer will keep repeating (and executing) even if its <#timerFunction> causes an error
  • data: <?> (optional) arbitrary data that will be passed to the <#timerFunction>

If delayOrStartTime is a <#timeOfDayString>, the timer will be scheduled to execute for the first time at the earliest occurrence given the repeatInterval, e.g.:

  • If it's 17:00, myTimer:runEvery("6h","0:00") will set the timer 1 hour from now (at 18:00)
  • If it's 19:00, myTimer:runEvery("6h","0:00") will set the timer 5 hour from now (at 0:00 tomorrow)
  • If it's 21:00, myTimer:runEvery("6h","20:00") will set the timer 5 hours from now (at 2:00 tomorrow)

Usage:

-- run a job every day at 8, regardless of when Hammermoon was (re)started:
hm.timer.new(doThisEveryMorning,myData):runEvery("1d","8:00")

-- run a job every hour on the hour from 8:00 to 20:00:
for h=8,20 do hm.timer.new(runJob):runEvery("1d",h..":00") end

-- start doing something every second in 5 seconds:
local myTimer=hm.timer.new(mustDoThisVeryOften)
myTimer:runEvery(1,5)
-- and later (maybe in some event callback), stop:
myTimer:cancel()

Method <#timer>:runIn(delay,data)

API CHANGE: This replaces non-repeating timers (hs.timer.new() and hs.timer.doAfter()) as well as hs.timer.delayeds

INTERNAL CHANGE: These timers technically "repeat" into the distant future, so they can be reused at will, but are transparently added to and removed from the run loop as needed

Schedules execution of the timer after a given delay.

Every time you call this method the "execution countdown" is restarted - i.e. any previous schedule (created with any of the :run...() methods) is overwritten. This can be useful to coalesce processing of unpredictable asynchronous events into a single callback; for example, if you have an event stream that happens in "bursts" of dozens of events at once, use an appropriate delay to wait for things to settle down, and then your callback will run just once.

Usage:

local coalesceTimer=hm.timer.new(doSomethingExpensiveOnlyOnce)
local function burstyEventCallback(...)
  coalesceTimer:runIn(2.5) -- wait 2.5 seconds after the last event in the burst
end

Method <#timer>:runWhen(predicateFn,checkInterval,continueOnError,data)

API CHANGE: Not (directly) available in HS, but of dubious utility anyway.

Schedules execution of the timer every time a given predicate is true.

  • predicateFn: <#predicateFunction> A predicate function that determines whether to execute the timer
  • checkInterval: <#intervalString> interval between predicate checks (and potential timer executions)
  • continueOnError: <#boolean> (optional) if true, predicateFn will keep being checked even if it - or the timer's <#timerFunction> - causes an error
  • data: <?> (optional) arbitrary data that will be passed to the <#predicateFunction> and <#timerFunction>

The given predicateFn will start being checked right away. Every time it returns true, the timer will execute.

Method <#timer>:runWhile(predicateFn,checkInterval,continueOnError,data)

API CHANGE: Replaces hs.timer.doWhile() and hs.timer.doUntil()

Schedules repeated execution of the timer while a given predicate remains true.

  • predicateFn: <#predicateFunction> A predicate function that determines whether to contine executing the timer
  • checkInterval: <#intervalString> interval between predicate checks (and timer executions)
  • continueOnError: <#boolean> (optional) if true, the timer will keep repeating (and executing) even if its <#timerFunction> or predicateFn cause an error
  • data: <?> (optional) arbitrary data that will be passed to the <#predicateFunction> and <#timerFunction>

The given predicateFn will start being checked right away. While it returns true, the timer will execute; as soon as it returns false the timer will be canceled.

Method <#timer>:setFn(fn) -> self

Sets the function for this timer.

  • fn: <#function>

  • Returns self: <#timer>


Type intervalString

Extends <#string>

A string describing a time interval.

The following are valid formats: "DDdHHh", "HHhMMm", "MMmSSs", "DDd", "HHh", "MMm", "SSs", "NNNNms" - they represent an interval in days, hours, minutes, seconds and/or milliseconds. You can also use a plain number (in seconds) wherever this type is expected.

Examples: "1m30s" or 90 (in seconds); "1500ms" or 1.5.


Type timeOfDayString

Extends <#string>

A string describing a time of day.

The following are valid formats: "HH:MM:SS", "HH:MM" or "HHMM" - they represent a time of day in hours, minutes, seconds (24-hour clock) You can also use a plain number (in seconds after midnight) wherever this type is expected.

Examples: "8:00:00" or "800" or 28800 (in seconds).


Function prototype predicateFunction(data) -> <#boolean>

API CHANGE: Predicate functions can receive arbitrary data.

A predicate function that controls conditional execution of a timer.

  • data: <?> the arbitrary data for this timer, or if "timer" was passed to new(), the timer itself

  • Returns <#boolean>: the return value will determine wheter to run, repeat, skip or cancel altogether the timer's execution, depending on what method was used

Function prototype timerFunction(timer,data)

API CHANGE: Timer callbacks can receive arbitrary data.

A function that will be executed by a timer.

  • timer: <#timer> the timer that scheduled execution of this function
  • data: <?> the arbitrary data for this timer, or if "timer" was passed to new(), the timer itself