new object $heart: $utilities; var $heart heart_failures = []; var $heart hearts = [[$lag_watcher, 872013847], [$world, 872014008]]; var $heart info = #[[$world, [600, 872013408]], [$lag_watcher, [14, 872013833]]]; var $root created_on = 796268969; var $root flags = ['methods, 'code, 'variables, 'core]; var $root inited = 1; var $root managed = [$heart]; var $root manager = $heart; private method ._add_heartbeat() { arg obj, delay; var when, h, values; // Only one heartbeat per object ._del_heartbeat(obj); when = delay + time(); info = dict_add(info, obj, [delay, time()]); for h in [1 .. listlen(hearts)] { if (((hearts[h])[2]) >= when) { hearts = insert(hearts, h, [obj, when]); return; } } hearts += [[obj, when]]; }; private method ._del_heartbeat() { arg obj; var x, pos; if (info.contains(obj)) info = info.del(obj); for x in [1 .. listlen(hearts)] { if (((hearts[x])[1]) == obj) { hearts = delete(hearts, x); return 1; } } return 0; }; public method .add_heartbeat() { arg @delay; [(delay ?= 60)] = delay; ._add_heartbeat(sender(), delay); }; root method .core_heart(): nooverride { var h; for h in (hearts) { if (!valid(h[1])) ._del_heartbeat(h[1]); } }; public method .del_heartbeat() { if (!(._del_heartbeat(sender()))) throw(~objnf, ("Sender (" + sender()) + ") does not have a heartbeat."); }; public method .hearts() { return hearts; }; public method .pulse() { var heart, h, x, new; for heart in (hearts) { if ((heart[2]) > time()) break; if (!valid(heart[1])) ._del_heartbeat(heart[1]); catch any (> (heart[1]).pulse() <); with (| ((heart[1]).manager()).tell_traceback(traceback()) |); ._add_heartbeat(heart[1], (info[heart[1]])[1]); } };