parent $utilities object $scheduler_crag var $root child_index 0 var $root owners [$scheduler_crag] var $root owned [$scheduler_crag] var $root fertile 0 var $root inited 1 var $scheduler_crag tasks <$small_first_heap_class, #[['key, 'run_time], ['data, [#[['tid, 7], ['run_time, 762498497], ['instime, 762498467], ['sender, $], ['caller, $], ['method, 'tell], ['flags, ['system]], ['owner, $], ['args, ["foo"]]], #[['tid, 8], ['run_time, 762498498], ['instime, 762498468], ['sender, $], ['caller, $], ['method, 'tell], ['flags, ['system]], ['owner, $], ['args, ["foo"]]], #[['tid, 9], ['run_time, 762498499], ['instime, 762498469], ['sender, $], ['caller, $], ['method, 'tell], ['flags, ['system]], ['owner, $], ['args, ["foo"]]], #[['tid, 10], ['run_time, 762498500], ['instime, 762498470], ['sender, $], ['caller, $], ['method, 'tell], ['flags, ['system]], ['owner, $], ['args, ["foo"]]], #[['tid, 11], ['run_time, 762498506], ['instime, 762498503], ['sender, $], ['caller, $], ['method, 'tell], ['flags, ['system]], ['owner, $], ['args, ["foo"]]]]]]> var $scheduler_crag task_index 12 var $root manager $scheduler_crag var $root writable [$scheduler_crag] var $root readable ['parameters, 'methods, 'code] var $root dbref 'scheduler_crag method _insert_task arg tid, extime, instime, sender, caller, method, flags, owner, args; // inserts a task into the correct order. Callable only by this. if (sender() != this()) throw(~perm, "Sender is not this"); tasks = tasks.add(#[['tid, tid], ['run_time, extime + instime], ['instime, instime], ['sender, sender], ['caller, caller], ['method, method], ['flags, flags], ['owner, owner], ['args, args]]); . method pulse // called by $sys.heartbeat. if (caller() != $sys) throw(~perm, "Sender is not system"); while ((tasks.length()) && ((time() > ((tasks.element(1))['run_time])) && (._run_task()))) { // do nothing? } . method _run_task var task, code, args, a; // called by $scheduler only if (caller() != this()) throw(~perm, "Caller is not this"); task = tasks.element(1); catch any { // setup the args by hand, becuase we use eval and it expects a string args = task['args]; if (args) { for a in [1 .. listlen(args)] args = replace(args, a, $data.unparse(args[a])); args = $list.to_string(args, ","); } else { args = ""; } code = ((("." + tostr(task['method])) + "(") + args) + ");"; // run it through eval as the sender(): (task['caller]).eval([code], task['sender]); return ._del_task(1); } with handler { // bounce the errors to the person, or to the system board if it's 'system catch any { (task['owner]).tell(["SCHEDULER ERROR: ", @traceback()]); } with handler { if ((task['owner]) == 'system) { $channels.announce('System, traceback()[1]); $channels.announce('System, "task: " + ($data.unparse(task))); } } return 0; } . method queue arg [owner]; var task, atasks, queue, t; // return tasks queued under owner, or return all if is admin. if ((!owner) && ($sys.is_admin(sender()))) owner = 'all; else owner = [@owner, sender()][1]; // if (owner == 'all) // atasks = tasks; // else // atasks = owners[owner]; if (owner || (!($sys.is_admin(sender())))) { queue = $small_first_heap_class.new([], 'run_time); for t in [1 .. queue.length()] { if (((tasks.element(t))['owner]) == owner) queue.add(tasks.element(t)); } } else { queue = tasks; } return queue; . method del_task arg tid; var task; if (type(tid) != 'integer) throw(~type, "Task Identification must be an integer"); if (!(tid in tasks)) throw(~tasknf, ("No task found by the TID of `" + tostr(tid)) + "'"); if ((task_owner[tid]) != sender()) throw(~perm, "Sender does not have permissions to kill this task."); // ok, delete it ._del_task(tid in ($list.slice(.tasks(), 'tid))); . method tasks return tasks.data(); . method sys_del_task arg tid; var task; // sender must be system if (!($sys.is_agent(sender()))) throw(~perm, "Sender does not have system privelages"); if (type(tid) != 'integer) throw(~type, "Task Identification must be an integer"); if (!(tid in tasks)) throw(~tasknf, ("No task found by the TID of `" + tostr(tid)) + "'"); // ok, delete it. ._del_task(tid in ($list.slice(.tasks(), 'tid))); . method _del_task arg task; // assumes that the $scheduler has already checked everything. if (sender() != this()) throw(~perm, "Sender is not this"); tasks = tasks.del(task); . method sys_bump_task arg tid; var task_index, task; // bumps a task up to be executed next if ((!($sys.is_agent(sender()))) || (!($sys.is_admin(sender())))) throw(~perm, "Sender does not have system perms"); // the meat task_index = tid in (.tasks()); if (!task_index) throw(~tasknf, "Task not found."); if (task_index == 1) return; task = tasks.element(task_index); tasks = tasks.del(task_index); task = task.replace('run_time, $list.min(((tasks.element(1))['run_time]) - 1, time())); tasks = tasks.add(task); . method add_task arg time, method, [args]; var tid, flags, owner, task; // use `@info $scheduler' for more information. // time is seconds from insertion time that it will be run (ie 300 == 5 mins) // if ((type(time) != 'integer) || ((type(method) != 'symbol) || (type(args) != 'list))) throw(~type, "Arguments are not an integer, symbol, and list."); if (time < 1) throw(~time, "Time is negative."); if (time > 31536000) throw(~time, "Try to schedule a task LESS than a year from now?"); // get TID and increment the TID index task_index = task_index + 1; tid = task_index; // flags can be set in a system only add_task, for now set them as 'system flags = ['system]; // check the owner of the object sending the task owner = sender().owner(); // do it. task = [tid, time, time(), sender(), caller(), method, flags, owner, args]; ._insert_task(@task); .