diff options
Diffstat (limited to 'advtrains_line_automation/scheduler.lua')
-rw-r--r-- | advtrains_line_automation/scheduler.lua | 133 |
1 files changed, 0 insertions, 133 deletions
diff --git a/advtrains_line_automation/scheduler.lua b/advtrains_line_automation/scheduler.lua deleted file mode 100644 index 6025b02..0000000 --- a/advtrains_line_automation/scheduler.lua +++ /dev/null @@ -1,133 +0,0 @@ --- scheduler.lua --- Implementation of a Railway time schedule queue --- In contrast to the LuaATC interrupt queue, this one can handle many different --- event receivers. This is done by registering a callback with the scheduler - -local ln = advtrains.lines -local sched = {} - -local UNITS_THRESH = 10 -local MAX_PER_ITER = 10 - -local callbacks = {} - --- Register a handler callback to handle scheduler items. --- e - a handler identifier (corresponds to "handler" in enqueue() ) --- func - a function(evtdata) to be executed when a schedule item expires --- evtdata - arbitrary data that has been passed into enqueue() -function sched.register_callback(e, func) - callbacks[e] = func -end - ---[[ -{ - t = <railway time in seconds> - e = <handler callback> - d = <data table> - u = <unit identifier> -} -The "unit identifier" is there to prevent schedule overflows. It can be, for example, the position hash -of a node or a train ID. If the number of schedules for a unit exceeds UNITS_THRESH, further schedules are -blocked. -]]-- -local queue = {} - -local units_cnt = {} - -function sched.load(data) - if data then - for i,elem in ipairs(data) do - table.insert(queue, elem) - units_cnt[elem.u] = (units_cnt[elem.u] or 0) + 1 - end - atlog("[lines][scheduler] Loaded the schedule queue,",#data,"items.") - end -end -function sched.save() - return queue -end - -function sched.run() - local ctime = ln.rwt.get_time() - local cnt = 0 - local ucn, elem - while cnt <= MAX_PER_ITER do - elem = queue[1] - if elem and elem.t <= ctime then - table.remove(queue, 1) - if callbacks[elem.e] then - -- run it - callbacks[elem.e](elem.d) - else - atwarn("[lines][scheduler] No callback to handle schedule",elem) - end - cnt=cnt+1 - ucn = units_cnt[elem.u] - if ucn and ucn>0 then - units_cnt[elem.u] = ucn - 1 - end - else - break - end - end -end - --- Enqueue a new scheduled item to be executed at "rwtime" --- handler: a string identifying the handler to use (registered with sched.register_callback()) --- evtdata: Arbitrary Lua data to be passed to the handler callback --- unitid: An arbitrary string uniquely identifying the thing that is issuing this enqueue. --- used to prevent expotentially growing "scheduler bombs" --- unitlim: Custom override for UNITS_THRESH (see there) -function sched.enqueue(rwtime, handler, evtdata, unitid, unitlim) - local qtime = ln.rwt.to_secs(rwtime) - assert(type(handler)=="string") - assert(type(unitid)=="string") - assert(type(unitlim)=="number") - - local cnt=1 - local ucn, elem - - ucn = (units_cnt[unitid] or 0) - local ulim=(unitlim or UNITS_THRESH) - if ucn >= ulim then - atlog("[lines][scheduler] discarding enqueue for",handler,"(limit",ulim,") because unit",unitid,"has already",ucn,"schedules enqueued") - return false - end - - while true do - elem = queue[cnt] - if not elem or elem.t > qtime then - table.insert(queue, cnt, { - t=qtime, - e=handler, - d=evtdata, - u=unitid, - }) - units_cnt[unitid] = ucn + 1 - return true - end - cnt = cnt+1 - end -end - --- See enqueue(). Same meaning, except that rwtime is relative to now. -function sched.enqueue_in(rwtime, handler, evtdata, unitid, unitlim) - local ctime = ln.rwt.get_time() - local rwtime_s = ln.rwt.to_secs(rwtime) - sched.enqueue(ctime + rwtime_s, handler, evtdata, unitid, unitlim) -end - --- Discards all schedules for unit "unitid" (removes them from the queue) -function sched.discard_all(unitid) - local i = 1 - while i<=#queue do - if queue[i].u == unitid then - table.remove(queue,i) - else - i=i+1 - end - end - units_cnt[unitid] = 0 -end - -ln.sched = sched |