Manage timer callback reference counts
This commit is contained in:
parent
d3a3a89098
commit
fab723b9bc
@ -747,13 +747,19 @@ python_timer_callback(id_type timer_id, void *data) {
|
|||||||
else Py_DECREF(ret);
|
else Py_DECREF(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
python_timer_cleanup(id_type timer_id UNUSED, void *data) {
|
||||||
|
if (data) Py_DECREF((PyObject*)data);
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
add_python_timer(PyObject *self UNUSED, PyObject *args) {
|
add_python_timer(PyObject *self UNUSED, PyObject *args) {
|
||||||
PyObject *callback;
|
PyObject *callback;
|
||||||
double interval;
|
double interval;
|
||||||
const char *name;
|
const char *name;
|
||||||
if (!PyArg_ParseTuple(args, "sOd", &name, &callback, &interval)) return NULL;
|
if (!PyArg_ParseTuple(args, "sOd", &name, &callback, &interval)) return NULL;
|
||||||
unsigned long long timer_id = add_timer(&main_event_loop, name, interval, 1, python_timer_callback, callback);
|
unsigned long long timer_id = add_timer(&main_event_loop, name, interval, 1, python_timer_callback, callback, python_timer_cleanup);
|
||||||
|
Py_INCREF(callback);
|
||||||
return Py_BuildValue("K", timer_id);
|
return Py_BuildValue("K", timer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -860,6 +866,7 @@ main_loop(ChildMonitor *self, PyObject *a UNUSED) {
|
|||||||
}
|
}
|
||||||
has_open_windows = process_pending_closes(self);
|
has_open_windows = process_pending_closes(self);
|
||||||
}
|
}
|
||||||
|
remove_all_timers(&main_event_loop);
|
||||||
if (PyErr_Occurred()) return NULL;
|
if (PyErr_Occurred()) return NULL;
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,7 +22,7 @@ update_timers(EventLoopData *eld) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
id_type
|
id_type
|
||||||
add_timer(EventLoopData *eld, const char *name, double interval, int enabled, timer_callback_func cb, void *cb_data) {
|
add_timer(EventLoopData *eld, const char *name, double interval, int enabled, timer_callback_func cb, void *cb_data, timer_cleanup_func cleanup) {
|
||||||
if (eld->timers_count >= sizeof(eld->timers)/sizeof(eld->timers[0])) {
|
if (eld->timers_count >= sizeof(eld->timers)/sizeof(eld->timers[0])) {
|
||||||
fprintf(stderr, "Too many timers added\n");
|
fprintf(stderr, "Too many timers added\n");
|
||||||
return 0;
|
return 0;
|
||||||
@ -33,24 +33,34 @@ add_timer(EventLoopData *eld, const char *name, double interval, int enabled, ti
|
|||||||
t->trigger_at = enabled ? monotonic() + interval : DBL_MAX;
|
t->trigger_at = enabled ? monotonic() + interval : DBL_MAX;
|
||||||
t->callback = cb;
|
t->callback = cb;
|
||||||
t->callback_data = cb_data;
|
t->callback_data = cb_data;
|
||||||
|
t->cleanup = cleanup;
|
||||||
t->id = ++timer_counter;
|
t->id = ++timer_counter;
|
||||||
update_timers(eld);
|
update_timers(eld);
|
||||||
return t->id;
|
return t->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define removeX(which, item_id, update_func) {\
|
|
||||||
for (nfds_t i = 0; i < eld->which##_count; i++) { \
|
|
||||||
if (eld->which[i].id == item_id) { \
|
|
||||||
eld->which##_count--; \
|
|
||||||
if (i < eld->which##_count) { \
|
|
||||||
memmove(eld->which + i, eld->which + i + 1, sizeof(eld->which[0]) * (eld->which##_count - i)); \
|
|
||||||
} \
|
|
||||||
update_func(eld); break; \
|
|
||||||
}}}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
remove_timer(EventLoopData *eld, id_type timer_id) {
|
remove_timer(EventLoopData *eld, id_type timer_id) {
|
||||||
removeX(timers, timer_id, update_timers);
|
for (nfds_t i = 0; i < eld->timers_count; i++) {
|
||||||
|
if (eld->timers[i].id == timer_id) {
|
||||||
|
if (eld->timers[i].cleanup) eld->timers[i].cleanup(timer_id, eld->timers[i].callback_data);
|
||||||
|
eld->timers_count--;
|
||||||
|
if (i < eld->timers_count) {
|
||||||
|
memmove(eld->timers + i, eld->timers + i + 1, sizeof(eld->timers[0]) * (eld->timers_count - i));
|
||||||
|
}
|
||||||
|
update_timers(eld);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
remove_all_timers(EventLoopData *eld) {
|
||||||
|
while (eld->timers_count) {
|
||||||
|
eld->timers_count--;
|
||||||
|
if (eld->timers[eld->timers_count].cleanup) eld->timers[eld->timers_count].cleanup(eld->timers[eld->timers_count].id, eld->timers[eld->timers_count].callback_data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@ -9,11 +9,13 @@
|
|||||||
#include "data-types.h"
|
#include "data-types.h"
|
||||||
|
|
||||||
typedef void(*timer_callback_func)(id_type, void*);
|
typedef void(*timer_callback_func)(id_type, void*);
|
||||||
|
typedef void(*timer_cleanup_func)(id_type, void*);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
id_type id;
|
id_type id;
|
||||||
double interval, trigger_at;
|
double interval, trigger_at;
|
||||||
timer_callback_func callback;
|
timer_callback_func callback;
|
||||||
|
timer_cleanup_func cleanup;
|
||||||
void *callback_data;
|
void *callback_data;
|
||||||
const char *name;
|
const char *name;
|
||||||
} Timer;
|
} Timer;
|
||||||
@ -26,8 +28,9 @@ typedef struct {
|
|||||||
|
|
||||||
|
|
||||||
double prepare_for_poll(EventLoopData *eld, double timeout);
|
double prepare_for_poll(EventLoopData *eld, double timeout);
|
||||||
id_type add_timer(EventLoopData *eld, const char *name, double interval, int enabled, timer_callback_func cb, void *cb_data);
|
id_type add_timer(EventLoopData *eld, const char *name, double interval, int enabled, timer_callback_func cb, void *cb_data, timer_cleanup_func cleanup);
|
||||||
void remove_timer(EventLoopData *eld, id_type timer_id);
|
void remove_timer(EventLoopData *eld, id_type timer_id);
|
||||||
|
void remove_all_timers(EventLoopData *eld);
|
||||||
void toggle_time(EventLoopData *eld, id_type timer_id, int enabled);
|
void toggle_time(EventLoopData *eld, id_type timer_id, int enabled);
|
||||||
void change_timer_interval(EventLoopData *eld, id_type timer_id, double interval);
|
void change_timer_interval(EventLoopData *eld, id_type timer_id, double interval);
|
||||||
unsigned int dispatch_timers(EventLoopData *eld);
|
unsigned int dispatch_timers(EventLoopData *eld);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user