Files
Aurora.3/code/controllers/Processes/scheduler.dm
Lohikar 7cc68feeb4 Remove holder access (#1906)
changes:

Mob holders no longer grant that mob's access.
Fix bug where wrong task was killed on invalid head in scheduler.
Fixes #1785
2017-03-12 12:18:09 +02:00

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