22
33#include < Python.h>
44
5+ /* *
6+ * @brief Wrapper to decrement the counter of queueing event-loop jobs after the job finishes
7+ */
58static PyObject *eventLoopJobWrapper (PyObject *jobFn, PyObject *Py_UNUSED (_)) {
69 PyObject *ret = PyObject_CallObject (jobFn, NULL ); // jobFn()
710 Py_XDECREF (ret); // don't care about its return value
11+ PyEventLoop::_locker->decCounter ();
812 Py_RETURN_NONE;
913}
1014static PyMethodDef jobWrapperDef = {" eventLoopJobWrapper" , eventLoopJobWrapper, METH_NOARGS, NULL };
1115
1216PyEventLoop::AsyncHandle PyEventLoop::enqueue (PyObject *jobFn) {
17+ PyEventLoop::_locker->incCounter ();
1318 PyObject *wrapper = PyCFunction_New (&jobWrapperDef, jobFn);
1419 // Enqueue job to the Python event-loop
1520 // https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.call_soon
@@ -18,6 +23,7 @@ PyEventLoop::AsyncHandle PyEventLoop::enqueue(PyObject *jobFn) {
1823}
1924
2025PyEventLoop::AsyncHandle PyEventLoop::enqueueWithDelay (PyObject *jobFn, double delaySeconds) {
26+ PyEventLoop::_locker->incCounter ();
2127 PyObject *wrapper = PyCFunction_New (&jobWrapperDef, jobFn);
2228 // Schedule job to the Python event-loop
2329 // https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.call_later
@@ -131,6 +137,14 @@ PyEventLoop PyEventLoop::getRunningLoop() {
131137}
132138
133139void PyEventLoop::AsyncHandle::cancel () {
140+ PyObject *scheduled = PyObject_GetAttrString (_handle, " _scheduled" ); // this attribute only exists on asyncio.TimerHandle returned by loop.call_later
141+ // NULL if no such attribute (on a strict asyncio.Handle returned by loop.call_soon)
142+ bool finishedOrCanceled = scheduled && scheduled == Py_False; // the job function has already been executed or canceled
143+ if (!finishedOrCanceled) {
144+ PyEventLoop::_locker->decCounter ();
145+ }
146+ Py_XDECREF (scheduled);
147+
134148 // https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.Handle.cancel
135149 PyObject *ret = PyObject_CallMethod (_handle, " cancel" , NULL ); // returns None
136150 Py_XDECREF (ret);
0 commit comments