summaryrefslogtreecommitdiffstats
path: root/Modules/_asynciomodule.c
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/_asynciomodule.c')
-rw-r--r--Modules/_asynciomodule.c45
1 files changed, 18 insertions, 27 deletions
diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c
index 0d6b21d..8847123 100644
--- a/Modules/_asynciomodule.c
+++ b/Modules/_asynciomodule.c
@@ -91,7 +91,7 @@ typedef struct {
PyObject *task_context;
int task_must_cancel;
int task_log_destroy_pending;
- int task_cancel_requested;
+ int task_num_cancels_requested;
} TaskObj;
typedef struct {
@@ -2036,7 +2036,7 @@ _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
Py_CLEAR(self->task_fut_waiter);
self->task_must_cancel = 0;
self->task_log_destroy_pending = 1;
- self->task_cancel_requested = 0;
+ self->task_num_cancels_requested = 0;
Py_INCREF(coro);
Py_XSETREF(self->task_coro, coro);
@@ -2191,11 +2191,13 @@ not return True (unless the task was already cancelled). A
task will be marked as cancelled when the wrapped coroutine
terminates with a CancelledError exception (even if cancel()
was not called).
+
+This also increases the task's count of cancellation requests.
[clinic start generated code]*/
static PyObject *
_asyncio_Task_cancel_impl(TaskObj *self, PyObject *msg)
-/*[clinic end generated code: output=c66b60d41c74f9f1 input=f4ff8e8ffc5f1c00]*/
+/*[clinic end generated code: output=c66b60d41c74f9f1 input=7bb51bf25974c783]*/
{
self->task_log_tb = 0;
@@ -2203,10 +2205,10 @@ _asyncio_Task_cancel_impl(TaskObj *self, PyObject *msg)
Py_RETURN_FALSE;
}
- if (self->task_cancel_requested) {
+ self->task_num_cancels_requested += 1;
+ if (self->task_num_cancels_requested > 1) {
Py_RETURN_FALSE;
}
- self->task_cancel_requested = 1;
if (self->task_fut_waiter) {
PyObject *res;
@@ -2238,51 +2240,40 @@ _asyncio_Task_cancel_impl(TaskObj *self, PyObject *msg)
/*[clinic input]
_asyncio.Task.cancelling
-Return True if the task is in the process of being cancelled.
-
-This is set once .cancel() is called
-and remains set until .uncancel() is called.
+Return the count of the task's cancellation requests.
-As long as this flag is set, further .cancel() calls will be ignored,
-until .uncancel() is called to reset it.
+This count is incremented when .cancel() is called
+and may be decremented using .uncancel().
[clinic start generated code]*/
static PyObject *
_asyncio_Task_cancelling_impl(TaskObj *self)
-/*[clinic end generated code: output=803b3af96f917d7e input=c50e50f9c3ca4676]*/
+/*[clinic end generated code: output=803b3af96f917d7e input=b625224d310cbb17]*/
/*[clinic end generated code]*/
{
- if (self->task_cancel_requested) {
- Py_RETURN_TRUE;
- }
- else {
- Py_RETURN_FALSE;
- }
+ return PyLong_FromLong(self->task_num_cancels_requested);
}
/*[clinic input]
_asyncio.Task.uncancel
-Reset the flag returned by cancelling().
+Decrement the task's count of cancellation requests.
This should be used by tasks that catch CancelledError
and wish to continue indefinitely until they are cancelled again.
-Returns the previous value of the flag.
+Returns the remaining number of cancellation requests.
[clinic start generated code]*/
static PyObject *
_asyncio_Task_uncancel_impl(TaskObj *self)
-/*[clinic end generated code: output=58184d236a817d3c input=5db95e28fcb6f7cd]*/
+/*[clinic end generated code: output=58184d236a817d3c input=68f81a4b90b46be2]*/
/*[clinic end generated code]*/
{
- if (self->task_cancel_requested) {
- self->task_cancel_requested = 0;
- Py_RETURN_TRUE;
- }
- else {
- Py_RETURN_FALSE;
+ if (self->task_num_cancels_requested > 0) {
+ self->task_num_cancels_requested -= 1;
}
+ return PyLong_FromLong(self->task_num_cancels_requested);
}
/*[clinic input]