Make using the timer for wakeups more efficient

This commit is contained in:
Kovid Goyal 2017-09-07 21:11:29 +05:30
parent ff3ddfd369
commit a52f0939df
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 45 additions and 6 deletions

View File

@ -44,6 +44,16 @@ class Timers(_Timers):
timer = self.timer_hash.setdefault(timer, timer)
return _Timers.add(self, delay, timer, args) if args else _Timers.add(self, delay, timer)
def add_if_before(self, delay, timer, *args):
# Needed because bound methods are recreated on every access
timer = self.timer_hash.setdefault(timer, timer)
return _Timers.add_if_before(self, delay, timer, *args)
def add_if_missing(self, delay, timer, *args):
# Needed because bound methods are recreated on every access
timer = self.timer_hash.setdefault(timer, timer)
return _Timers.add_if_missing(self, delay, timer, *args)
def remove(self, timer):
# Needed because bound methods are recreated on every access
timer = self.timer_hash.setdefault(timer, timer)
@ -398,7 +408,7 @@ class Boss:
d = int(self.opts.cursor_blink_interval * 1000)
n = t // d
draw_cursor = n % 2 == 0
self.ui_timers.add_if_missing(
self.ui_timers.add_if_before(
((n + 1) * d / 1000) - now, wakeup_for_cursor_blink_render)
if draw_cursor:
with self.cursor_program:

View File

@ -321,7 +321,7 @@ parse_input(ChildMonitor *self) {
DECREF_CHILD(scratch[i]);
}
if (!parse_needed) {
timers_add(self->timers, self->repaint_delay - time_since_last_parse, false, Py_None, NULL);
timers_add_if_before(self->timers, self->repaint_delay - time_since_last_parse, Py_None, NULL);
}
}

View File

@ -355,6 +355,7 @@ double timers_timeout(Timers*);
void timers_call(Timers*);
bool timers_add(Timers *self, double delay, bool, PyObject *callback, PyObject *args);
bool timers_add_if_missing(Timers *self, double delay, PyObject *callback, PyObject *args);
bool timers_add_if_before(Timers *self, double delay, PyObject *callback, PyObject *args);
bool set_iutf8(int, bool);
color_type colorprofile_to_color(ColorProfile *self, color_type entry, color_type defval);

View File

@ -96,10 +96,8 @@ _add(Timers *self, double at, PyObject *callback, PyObject *args) {
return true;
}
bool
timers_add(Timers *self, double delay, bool update, PyObject *callback, PyObject *args) {
double at = monotonic_() + delay;
static inline bool
timers_add_(Timers *self, double at, bool update, PyObject *callback, PyObject *args) {
for (size_t i = 0; i < self->count; i++) {
if (self->events[i].callback == callback) {
self->events[i].at = update ? at : MIN(at, self->events[i].at);
@ -113,6 +111,11 @@ timers_add(Timers *self, double delay, bool update, PyObject *callback, PyObject
return _add(self, at, callback, args);
}
bool
timers_add(Timers *self, double delay, bool update, PyObject *callback, PyObject *args) {
return timers_add_(self, monotonic_() + delay, update, callback, args);
}
static PyObject *
add(Timers *self, PyObject *fargs) {
@ -124,6 +127,28 @@ add(Timers *self, PyObject *fargs) {
Py_RETURN_NONE;
}
bool
timers_add_if_before(Timers *self, double delay, PyObject *callback, PyObject *args) {
double at = monotonic_() + delay;
for (size_t i = 0; i < self->count; i++) {
if (self->events[i].at < at) {
return true;
}
}
return timers_add_(self, at, true, callback, args);
}
static PyObject *
add_if_before(Timers *self, PyObject *fargs) {
#define add_if_before_doc "add_if_before(delay, callback, args) -> Add callback, unless another callback scheduled before this one already exists."
PyObject *callback, *args = NULL;
double delay;
if (!PyArg_ParseTuple(fargs, "dO|O", &delay, &callback, &args)) return NULL;
if (!timers_add_if_before(self, delay, callback, args)) return NULL;
Py_RETURN_NONE;
}
bool
timers_add_if_missing(Timers *self, double delay, PyObject *callback, PyObject *args) {
@ -188,6 +213,8 @@ timers_call(Timers *self) {
size_t i, j;
for (i = 0, j = 0; i < self->count; i++) {
if (self->events[i].at <= now) { // expired, call it
/* PyObject_Print(self->events[i].callback, stdout, 1); */
/* printf("\n"); */
if (self->events[i].callback != Py_None) {
PyObject *ret = self->events[i].args ? PyObject_CallObject(self->events[i].callback, self->events[i].args) : PyObject_CallFunctionObjArgs(self->events[i].callback, NULL);
if (ret == NULL) PyErr_Print();
@ -214,6 +241,7 @@ call(Timers *self) {
static PyMethodDef methods[] = {
METHOD(add, METH_VARARGS)
METHOD(add_if_missing, METH_VARARGS)
METHOD(add_if_before, METH_VARARGS)
METHOD(remove_event, METH_O)
METHOD(timeout, METH_NOARGS)
METHOD(call, METH_NOARGS)