mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2025-12-21 07:32:02 +00:00
changes: Mob holders no longer grant that mob's access. Fix bug where wrong task was killed on invalid head in scheduler. Fixes #1785
167 lines
4.6 KiB
Plaintext
167 lines
4.6 KiB
Plaintext
/var/datum/controller/process/scheduler/scheduler
|
|
|
|
/************
|
|
* Scheduler *
|
|
************/
|
|
/datum/controller/process/scheduler
|
|
var/list/datum/scheduled_task/tasks = list()
|
|
var/datum/scheduled_task/head
|
|
|
|
/datum/controller/process/scheduler/setup()
|
|
name = "scheduler"
|
|
schedule_interval = 2
|
|
scheduler = src
|
|
|
|
/datum/controller/process/scheduler/doWork()
|
|
while (head && !PSCHED_CHECK_TICK)
|
|
if (head.destroyed)
|
|
head.kill()
|
|
head = head.next
|
|
tasks -= head
|
|
continue
|
|
if (head.trigger_time >= world.time)
|
|
return // Nothing after this will be ready to fire.
|
|
|
|
// This one's ready to fire, process it.
|
|
var/datum/scheduled_task/task = head
|
|
head = task.next
|
|
task.pre_process()
|
|
task.process()
|
|
task.post_process()
|
|
if (task.destroyed) // post_process probably destroyed it.
|
|
tasks -= task
|
|
task.kill()
|
|
|
|
/datum/controller/process/scheduler/proc/queue(datum/scheduled_task/task)
|
|
if (!task || !task.trigger_time)
|
|
warning("scheduler: Invalid task queued! Ignoring.")
|
|
return
|
|
// Reset this in-case we're doing a rebuild.
|
|
task.next = null
|
|
if (!head && !tasks.len)
|
|
head = task
|
|
tasks += task
|
|
return
|
|
|
|
if (!head) // Head's missing but we still have tasks, rebuild.
|
|
tasks += task
|
|
rebuild_queue()
|
|
return
|
|
|
|
var/datum/scheduled_task/curr = head
|
|
while (curr.next && curr.trigger_time < task.trigger_time)
|
|
curr = curr.next
|
|
|
|
if (!curr.next)
|
|
// We're at the end of the queue, just append.
|
|
curr.next = task
|
|
tasks += task
|
|
return
|
|
|
|
// Inserting midway into the list.
|
|
var/old_next = curr.next
|
|
curr.next = task
|
|
task.next = old_next
|
|
tasks += task
|
|
|
|
// Rebuilds the queue linked-list, removing invalid or destroyed entries.
|
|
/datum/controller/process/scheduler/proc/rebuild_queue()
|
|
log_debug("scheduler: Rebuilding queue.")
|
|
var/list/old_tasks = tasks
|
|
tasks = list()
|
|
if (!old_tasks.len)
|
|
log_debug("scheduler: rebuild was called on empty queue! Aborting.")
|
|
return
|
|
|
|
// Find the head.
|
|
for (var/thing in old_tasks)
|
|
var/datum/scheduled_task/task = thing
|
|
if (QDELETED(task))
|
|
old_tasks -= task
|
|
continue
|
|
|
|
if (task.destroyed)
|
|
old_tasks -= task
|
|
task.kill()
|
|
continue
|
|
|
|
if (!head || task.trigger_time < head.trigger_time)
|
|
head = task
|
|
|
|
if (!head)
|
|
log_debug("scheduler: unable to find head! Purging task queue.")
|
|
for (var/thing in old_tasks)
|
|
var/datum/scheduled_task/task = thing
|
|
if (QDELETED(task))
|
|
continue
|
|
|
|
task.kill()
|
|
|
|
head = null
|
|
return
|
|
|
|
// Don't queue the head.
|
|
tasks += head
|
|
old_tasks -= head
|
|
|
|
// Now rebuild the queue.
|
|
for (var/thing in old_tasks)
|
|
var/datum/scheduled_task/task = thing
|
|
|
|
queue(task)
|
|
|
|
log_debug("scheduler: Queue diff is [old_tasks.len - tasks.len].")
|
|
|
|
/datum/controller/process/scheduler/statProcess()
|
|
..()
|
|
stat(null, "[tasks.len] task\s")
|
|
|
|
/datum/controller/process/scheduler/proc/schedule(var/datum/scheduled_task/st)
|
|
queue(st)
|
|
|
|
/datum/controller/process/scheduler/proc/unschedule(var/datum/scheduled_task/st)
|
|
st.destroyed = TRUE
|
|
|
|
/**********
|
|
* Helpers *
|
|
**********/
|
|
/proc/schedule(source, the_proc, time, ...)
|
|
if (time < 0)
|
|
return
|
|
time += world.time
|
|
var/list/the_args
|
|
if (length(args) > 3)
|
|
the_args = args.Copy(4)
|
|
else
|
|
the_args = list()
|
|
if (source)
|
|
return schedule_task_with_source(time, the_proc, the_args)
|
|
else
|
|
return schedule_task(time, the_proc, the_args)
|
|
|
|
/proc/schedule_task_in(var/in_time, var/procedure, var/list/arguments = list())
|
|
return schedule_task(world.time + in_time, procedure, arguments)
|
|
|
|
/proc/schedule_task_with_source_in(var/in_time, var/source, var/procedure, var/list/arguments = list())
|
|
return schedule_task_with_source(world.time + in_time, source, procedure, arguments)
|
|
|
|
/proc/schedule_task(var/trigger_time, var/procedure, var/list/arguments)
|
|
var/datum/scheduled_task/st = new/datum/scheduled_task(trigger_time, procedure, arguments, /proc/destroy_scheduled_task, list())
|
|
scheduler.schedule(st)
|
|
return st
|
|
|
|
/proc/schedule_task_with_source(var/trigger_time, var/source, var/procedure, var/list/arguments)
|
|
var/datum/scheduled_task/st = new/datum/scheduled_task/source(trigger_time, source, procedure, arguments, /proc/destroy_scheduled_task, list())
|
|
scheduler.schedule(st)
|
|
return st
|
|
|
|
/proc/schedule_repeating_task(var/trigger_time, var/repeat_interval, var/procedure, var/list/arguments)
|
|
var/datum/scheduled_task/st = new/datum/scheduled_task(trigger_time, procedure, arguments, /proc/repeat_scheduled_task, list(repeat_interval))
|
|
scheduler.schedule(st)
|
|
return st
|
|
|
|
/proc/schedule_repeating_task_with_source(var/trigger_time, var/repeat_interval, var/source, var/procedure, var/list/arguments)
|
|
var/datum/scheduled_task/st = new/datum/scheduled_task/source(trigger_time, source, procedure, arguments, /proc/repeat_scheduled_task, list(repeat_interval))
|
|
scheduler.schedule(st)
|
|
return st
|