This commit is contained in:
DragonTrance
2022-11-11 10:00:39 -05:00
parent bb9bacf7dc
commit 55aecea4a6
+35 -88
View File
@@ -109,8 +109,6 @@ SUBSYSTEM_DEF(timer)
if (MC_TICK_CHECK)
return
var/static/list/spent = list()
var/static/datum/timedevent/timer
if (practical_offset > BUCKET_LEN)
head_offset += TICKS2DS(BUCKET_LEN)
practical_offset = 1
@@ -121,110 +119,59 @@ SUBSYSTEM_DEF(timer)
bucket_list = src.bucket_list
resumed = FALSE
if (!resumed)
timer = null
while (practical_offset <= BUCKET_LEN && head_offset + (practical_offset*world.tick_lag) <= world.time)
var/datum/timedevent/head = bucket_list[practical_offset]
if (!timer || !head || timer == head)
head = bucket_list[practical_offset]
timer = head
while (timer)
var/datum/timedevent/timer
while ((timer = bucket_list[practical_offset]))
var/datum/callback/callBack = timer.callBack
if (!callBack)
bucket_resolution = null //force bucket recreation
CRASH("Invalid timer: [get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]")
timer.bucketEject() //pop the stack
if (!timer.spent)
spent += timer
timer.spent = world.time
callBack.InvokeAsync()
last_invoke_tick = world.time
if (timer.flags & TIMER_LOOP)
timer.spent = 0
timer.timeToRun = world.time + timer.wait
timer.bucketJoin() //push the stack
if (MC_TICK_CHECK)
return
timer = timer.next
if (timer == head)
break
//Empty the bucket, check if anything in the secondary queue should be shifted to this bucket
if (!bucket_list[practical_offset])
bucket_list[practical_offset++] = null
var/i = 0
for(i in 1 to length(second_queue))
timer = second_queue[i]
if(timer.timeToRun >= TIMER_MAX) //Invalid timer
i--
break
bucket_list[practical_offset++] = null
//Check for timers that were scheduled to run in the past
if (timer.timeToRun < head_offset)
bucket_resolution = null //force bucket recreation
stack_trace("[i] Invalid timer state: Timer in long run queue with a time to run less then head_offset. \
[get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]")
break
//we freed up a bucket, lets see if anything in second_queue needs to be shifted to that bucket.
var/i = 0
var/L = length(second_queue)
for (i in 1 to L)
timer = second_queue[i]
if (timer.timeToRun >= TIMER_MAX)
i--
break
//Check for timers that are not capable of being scheduled to run without rebuilding buckets
if (timer.timeToRun < head_offset + TICKS2DS(practical_offset - 1))
bucket_resolution = null // force bucket recreation
stack_trace("[i] Invalid timer state: Timer in long run queue that would require a backtrack to transfer to short run queue. \
[get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]")
break
if (timer.timeToRun < head_offset)
bucket_resolution = null //force bucket recreation
CRASH("[i] Invalid timer state: Timer in long run queue with a time to run less then head_offset. [get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]")
timer.bucketJoin()
if (i)
second_queue.Cut(1, i+1)
if (timer.callBack && !timer.spent)
timer.callBack.InvokeAsync()
spent += timer
bucket_count++
else if(!QDELETED(timer))
qdel(timer)
continue
if (timer.timeToRun < head_offset + TICKS2DS(practical_offset))
bucket_resolution = null //force bucket recreation
CRASH("[i] Invalid timer state: Timer in long run queue that would require a backtrack to transfer to short run queue. [get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]")
if (timer.callBack && !timer.spent)
timer.callBack.InvokeAsync()
spent += timer
bucket_count++
else if(!QDELETED(timer))
qdel(timer)
continue
bucket_count++
var/bucket_pos = max(1, BUCKET_POS(timer))
var/datum/timedevent/bucket_head = bucket_list[bucket_pos]
if (!bucket_head)
bucket_list[bucket_pos] = timer
timer.next = null
timer.prev = null
continue
if (!bucket_head.prev)
bucket_head.prev = bucket_head
timer.next = bucket_head
timer.prev = bucket_head.prev
timer.next.prev = timer
timer.prev.next = timer
if (i)
second_queue.Cut(1, i+1)
timer = null
bucket_count -= length(spent)
for (var/i in spent)
var/datum/timedevent/qtimer = i
if(QDELETED(qtimer))
bucket_count++
continue
if(!(qtimer.flags & TIMER_LOOP))
qdel(qtimer)
else
bucket_count++
qtimer.spent = 0
qtimer.bucketEject()
if(qtimer.flags & TIMER_CLIENT_TIME)
qtimer.timeToRun = REALTIMEOFDAY + qtimer.wait
else
qtimer.timeToRun = world.time + qtimer.wait
qtimer.bucketJoin()
spent.len = 0
if (MC_TICK_CHECK)
break
//formated this way to be runtime resistant
/datum/controller/subsystem/timer/proc/get_timer_debug_string(datum/timedevent/TE)