mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-15 17:13:46 +01:00
Ports updated /tg/ timer subsystems.
This commit is contained in:
+108
-102
@@ -1,5 +1,5 @@
|
||||
#define BUCKET_LEN (world.fps*1*60) //how many ticks should we keep in the bucket. (1 minutes worth)
|
||||
#define BUCKET_POS(timer) ((round((timer.timeToRun - SStimer.head_offset) / world.tick_lag) % BUCKET_LEN) + 1)
|
||||
#define BUCKET_POS(timer) ((round((timer.timeToRun - SStimer.head_offset) / world.tick_lag) % BUCKET_LEN)||BUCKET_LEN)
|
||||
#define TIMER_MAX (world.time + TICKS2DS(min(BUCKET_LEN-(SStimer.practical_offset-DS2TICKS(world.time - SStimer.head_offset))-1, BUCKET_LEN-1)))
|
||||
#define TIMER_ID_MAX (2**24) //max float with integer precision
|
||||
|
||||
@@ -71,6 +71,7 @@ SUBSYSTEM_DEF(timer)
|
||||
for(var/I in second_queue)
|
||||
log_world(get_timer_debug_string(I))
|
||||
|
||||
var/cut_start_index = 1
|
||||
var/next_clienttime_timer_index = 0
|
||||
var/len = length(clienttime_timers)
|
||||
|
||||
@@ -90,11 +91,17 @@ SUBSYSTEM_DEF(timer)
|
||||
|
||||
ctime_timer.spent = REALTIMEOFDAY
|
||||
callBack.InvokeAsync()
|
||||
qdel(ctime_timer)
|
||||
|
||||
if(ctime_timer.flags & TIMER_LOOP)
|
||||
ctime_timer.spent = 0
|
||||
clienttime_timers.Insert(ctime_timer, 1)
|
||||
cut_start_index++
|
||||
else
|
||||
qdel(ctime_timer)
|
||||
|
||||
|
||||
if(next_clienttime_timer_index)
|
||||
clienttime_timers.Cut(1,next_clienttime_timer_index+1)
|
||||
clienttime_timers.Cut(cut_start_index,next_clienttime_timer_index+1)
|
||||
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
@@ -197,8 +204,22 @@ SUBSYSTEM_DEF(timer)
|
||||
|
||||
bucket_count -= length(spent)
|
||||
|
||||
for(var/spent_timer in spent)
|
||||
qdel(spent_timer)
|
||||
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
|
||||
|
||||
@@ -294,6 +315,7 @@ SUBSYSTEM_DEF(timer)
|
||||
var/id
|
||||
var/datum/callback/callBack
|
||||
var/timeToRun
|
||||
var/wait
|
||||
var/hash
|
||||
var/list/flags
|
||||
var/spent = 0 //time we ran the timer.
|
||||
@@ -302,14 +324,19 @@ SUBSYSTEM_DEF(timer)
|
||||
var/datum/timedevent/next
|
||||
var/datum/timedevent/prev
|
||||
|
||||
/datum/timedevent/New(datum/callback/callBack, timeToRun, flags, hash)
|
||||
/datum/timedevent/New(datum/callback/callBack, wait, flags, hash)
|
||||
var/static/nextid = 1
|
||||
id = TIMER_ID_NULL
|
||||
src.callBack = callBack
|
||||
src.timeToRun = timeToRun
|
||||
src.wait = wait
|
||||
src.flags = flags
|
||||
src.hash = hash
|
||||
|
||||
if(flags & TIMER_CLIENT_TIME)
|
||||
timeToRun = REALTIMEOFDAY + wait
|
||||
else
|
||||
timeToRun = world.time + wait
|
||||
|
||||
if(flags & TIMER_UNIQUE)
|
||||
SStimer.hashes[hash] = src
|
||||
|
||||
@@ -321,68 +348,15 @@ SUBSYSTEM_DEF(timer)
|
||||
nextid++
|
||||
SStimer.timer_id_dict[id] = src
|
||||
|
||||
name = "Timer: [id] (\ref[src]), TTR: [timeToRun], Flags: [jointext(bitfield2list(flags, list("TIMER_UNIQUE", "TIMER_OVERRIDE", "TIMER_CLIENT_TIME", "TIMER_STOPPABLE", "TIMER_NO_HASH_WAIT")), ", ")], callBack: \ref[callBack], callBack.object: [callBack.object]\ref[callBack.object]([getcallingtype()]), callBack.delegate:[callBack.delegate]([callBack.arguments ? callBack.arguments.Join(", ") : ""])"
|
||||
name = "Timer: [id] (\ref[src]), TTR: [timeToRun], Flags: [jointext(bitfield2list(flags, list("TIMER_UNIQUE", "TIMER_OVERRIDE", "TIMER_CLIENT_TIME", "TIMER_STOPPABLE", "TIMER_NO_HASH_WAIT", "TIMER_LOOP")), ", ")], callBack: \ref[callBack], callBack.object: [callBack.object]\ref[callBack.object]([getcallingtype()]), callBack.delegate:[callBack.delegate]([callBack.arguments ? callBack.arguments.Join(", ") : ""])"
|
||||
|
||||
if((timeToRun < world.time || timeToRun < SStimer.head_offset) && !(flags & TIMER_CLIENT_TIME))
|
||||
CRASH("Invalid timer state: Timer created that would require a backtrack to run (addtimer would never let this happen): [SStimer.get_timer_debug_string(src)]")
|
||||
|
||||
if(callBack.object != GLOBAL_PROC)
|
||||
if(callBack.object != GLOBAL_PROC && !QDESTROYING(callBack.object))
|
||||
LAZYADD(callBack.object.active_timers, src)
|
||||
|
||||
|
||||
var/list/L
|
||||
|
||||
if(flags & TIMER_CLIENT_TIME)
|
||||
L = SStimer.clienttime_timers
|
||||
else if(timeToRun >= TIMER_MAX)
|
||||
L = SStimer.second_queue
|
||||
|
||||
|
||||
if(L)
|
||||
//binary search sorted insert
|
||||
var/cttl = length(L)
|
||||
if(cttl)
|
||||
var/left = 1
|
||||
var/right = cttl
|
||||
var/mid = (left+right) >> 1 //rounded divide by two for hedgehogs
|
||||
|
||||
var/datum/timedevent/item
|
||||
while(left < right)
|
||||
item = L[mid]
|
||||
if(item.timeToRun <= timeToRun)
|
||||
left = mid+1
|
||||
else
|
||||
right = mid
|
||||
mid = (left+right) >> 1
|
||||
|
||||
item = L[mid]
|
||||
mid = item.timeToRun > timeToRun ? mid : mid+1
|
||||
L.Insert(mid, src)
|
||||
|
||||
else
|
||||
L += src
|
||||
return
|
||||
|
||||
//get the list of buckets
|
||||
var/list/bucket_list = SStimer.bucket_list
|
||||
|
||||
//calculate our place in the bucket list
|
||||
var/bucket_pos = BUCKET_POS(src)
|
||||
|
||||
//get the bucket for our tick
|
||||
var/datum/timedevent/bucket_head = bucket_list[bucket_pos]
|
||||
SStimer.bucket_count++
|
||||
//empty bucket, we will just add ourselves
|
||||
if(!bucket_head)
|
||||
bucket_list[bucket_pos] = src
|
||||
return
|
||||
//other wise, lets do a simplified linked list add.
|
||||
if(!bucket_head.prev)
|
||||
bucket_head.prev = bucket_head
|
||||
next = bucket_head
|
||||
prev = bucket_head.prev
|
||||
next.prev = src
|
||||
prev.next = src
|
||||
bucketJoin()
|
||||
|
||||
/datum/timedevent/Destroy()
|
||||
..()
|
||||
@@ -406,31 +380,7 @@ SUBSYSTEM_DEF(timer)
|
||||
|
||||
if(!spent)
|
||||
spent = world.time
|
||||
var/bucketpos = BUCKET_POS(src)
|
||||
var/datum/timedevent/buckethead
|
||||
var/list/bucket_list = SStimer.bucket_list
|
||||
if(bucketpos > 0)
|
||||
buckethead = bucket_list[bucketpos]
|
||||
|
||||
if(buckethead == src)
|
||||
bucket_list[bucketpos] = next
|
||||
SStimer.bucket_count--
|
||||
else if(timeToRun < TIMER_MAX || next || prev)
|
||||
SStimer.bucket_count--
|
||||
else
|
||||
var/l = length(SStimer.second_queue)
|
||||
SStimer.second_queue -= src
|
||||
if(l == length(SStimer.second_queue))
|
||||
SStimer.bucket_count--
|
||||
|
||||
if(prev == next && next)
|
||||
next.prev = null
|
||||
prev.next = null
|
||||
else
|
||||
if(prev)
|
||||
prev.next = next
|
||||
if(next)
|
||||
next.prev = prev
|
||||
bucketEject()
|
||||
else
|
||||
if(prev && prev.next == src)
|
||||
prev.next = next
|
||||
@@ -440,6 +390,66 @@ SUBSYSTEM_DEF(timer)
|
||||
prev = null
|
||||
return QDEL_HINT_IWILLGC
|
||||
|
||||
/datum/timedevent/proc/bucketEject()
|
||||
var/bucketpos = BUCKET_POS(src)
|
||||
var/list/bucket_list = SStimer.bucket_list
|
||||
var/list/second_queue = SStimer.second_queue
|
||||
var/datum/timedevent/buckethead
|
||||
if(bucketpos > 0)
|
||||
buckethead = bucket_list[bucketpos]
|
||||
if(buckethead == src)
|
||||
bucket_list[bucketpos] = next
|
||||
SStimer.bucket_count--
|
||||
else if(timeToRun < TIMER_MAX || next || prev)
|
||||
SStimer.bucket_count--
|
||||
else
|
||||
var/l = length(second_queue)
|
||||
second_queue -= src
|
||||
if(l == length(second_queue))
|
||||
SStimer.bucket_count--
|
||||
if(prev != next)
|
||||
prev.next = next
|
||||
next.prev = prev
|
||||
else
|
||||
if(prev)
|
||||
prev.next = null
|
||||
if(next)
|
||||
next.prev = null
|
||||
prev = next = null
|
||||
|
||||
/datum/timedevent/proc/bucketJoin()
|
||||
var/list/L
|
||||
|
||||
if(flags & TIMER_CLIENT_TIME)
|
||||
L = SStimer.clienttime_timers
|
||||
else if(timeToRun >= TIMER_MAX)
|
||||
L = SStimer.second_queue
|
||||
|
||||
if(L)
|
||||
BINARY_INSERT(src, L, datum/timedevent, timeToRun)
|
||||
return
|
||||
|
||||
//get the list of buckets
|
||||
var/list/bucket_list = SStimer.bucket_list
|
||||
|
||||
//calculate our place in the bucket list
|
||||
var/bucket_pos = BUCKET_POS(src)
|
||||
|
||||
//get the bucket for our tick
|
||||
var/datum/timedevent/bucket_head = bucket_list[bucket_pos]
|
||||
SStimer.bucket_count++
|
||||
//empty bucket, we will just add ourselves
|
||||
if(!bucket_head)
|
||||
bucket_list[bucket_pos] = src
|
||||
return
|
||||
//other wise, lets do a simplified linked list add.
|
||||
if(!bucket_head.prev)
|
||||
bucket_head.prev = bucket_head
|
||||
next = bucket_head
|
||||
prev = bucket_head.prev
|
||||
next.prev = src
|
||||
prev.next = src
|
||||
|
||||
/datum/timedevent/proc/getcallingtype()
|
||||
. = "ERROR"
|
||||
if(callBack.object == GLOBAL_PROC)
|
||||
@@ -452,13 +462,12 @@ SUBSYSTEM_DEF(timer)
|
||||
CRASH("addtimer called without a callback")
|
||||
|
||||
if(wait < 0)
|
||||
stack_trace("addtimer called with a negative wait. Converting to 0")
|
||||
stack_trace("addtimer called with a negative wait. Converting to [world.tick_lag]")
|
||||
|
||||
//alot of things add short timers on themselves in their destroy, we ignore those cases
|
||||
if(wait >= 1 && callback && callback.object && callback.object != GLOBAL_PROC && QDELETED(callback.object))
|
||||
stack_trace("addtimer called with a callback assigned to a qdeleted object")
|
||||
if(callback.object != GLOBAL_PROC && QDELETED(callback.object) && !QDESTROYING(callback.object))
|
||||
stack_trace("addtimer called with a callback assigned to a qdeleted object. In the future such timers will not be supported and may refuse to run or run with a 0 wait")
|
||||
|
||||
wait = max(wait, 0)
|
||||
wait = max(CEILING(wait, world.tick_lag), world.tick_lag)
|
||||
|
||||
if(wait >= INFINITY)
|
||||
CRASH("Attempted to create timer with INFINITY delay")
|
||||
@@ -468,9 +477,9 @@ SUBSYSTEM_DEF(timer)
|
||||
if(flags & TIMER_UNIQUE)
|
||||
var/list/hashlist
|
||||
if(flags & TIMER_NO_HASH_WAIT)
|
||||
hashlist = list(callback.object, "([callback.object.UID()])", callback.delegate, flags & TIMER_CLIENT_TIME)
|
||||
hashlist = list(callback.object, "(\ref[callback.object])", callback.delegate, flags & TIMER_CLIENT_TIME)
|
||||
else
|
||||
hashlist = list(callback.object, "([callback.object.UID()])", callback.delegate, wait, flags & TIMER_CLIENT_TIME)
|
||||
hashlist = list(callback.object, "(\ref[callback.object])", callback.delegate, wait, flags & TIMER_CLIENT_TIME)
|
||||
hashlist += callback.arguments
|
||||
hash = hashlist.Join("|||||||")
|
||||
|
||||
@@ -486,13 +495,10 @@ SUBSYSTEM_DEF(timer)
|
||||
if(hash_timer.flags & TIMER_STOPPABLE)
|
||||
. = hash_timer.id
|
||||
return
|
||||
else if(flags & TIMER_OVERRIDE)
|
||||
stack_trace("TIMER_OVERRIDE used without TIMER_UNIQUE")
|
||||
|
||||
|
||||
var/timeToRun = world.time + wait
|
||||
if(flags & TIMER_CLIENT_TIME)
|
||||
timeToRun = REALTIMEOFDAY + wait
|
||||
|
||||
var/datum/timedevent/timer = new(callback, timeToRun, flags, hash)
|
||||
var/datum/timedevent/timer = new(callback, wait, flags, hash)
|
||||
return timer.id
|
||||
|
||||
/proc/deltimer(id)
|
||||
@@ -515,4 +521,4 @@ SUBSYSTEM_DEF(timer)
|
||||
#undef BUCKET_LEN
|
||||
#undef BUCKET_POS
|
||||
#undef TIMER_MAX
|
||||
#undef TIMER_ID_MAX
|
||||
#undef TIMER_ID_MAX
|
||||
Reference in New Issue
Block a user