From c5da08a1406a5168b17343c85700724b2d93ac83 Mon Sep 17 00:00:00 2001 From: nocturn9x Date: Wed, 25 Mar 2020 11:27:29 +0100 Subject: [PATCH] Partial fix to the cancel method --- experiment.py | 8 ++++---- giambio/abstractions.py | 2 +- giambio/core.py | 10 ++++------ giambio/exceptions.py | 3 +++ giambio/traps.py | 9 +++++---- test.py | 1 - 6 files changed, 17 insertions(+), 16 deletions(-) diff --git a/experiment.py b/experiment.py index edf2c6e..8c3b8d3 100644 --- a/experiment.py +++ b/experiment.py @@ -45,11 +45,11 @@ async def main(): print("Spawning countdown immediately, scheduling count for 4 secs from now") task = loop.spawn(countdown(8)) task1 = loop.schedule(count(8, 2), 4) # Schedules the task, it will be ran 4 seconds from now - await giambio.sleep(0) # Act as a checkpoint to switch tasks. Beware! Cancelling a task straight away will propagate the error in the parent -# await task.cancel() # TODO: Fix this to reschedule the parent task properly - result = await task.join() + await giambio.sleep(0) # TODO: Fix this to avoid the need to use a checkpoint before cancelling + await task.cancel() +# result = await task.join() # Would raise TaskError! result1 = await task1.join() - print(f"countdown returned: {result}\ncount returned: {result1}") + print(f"countdown returned: {None}\ncount returned: {result1}") print("All done") loop.start(main) diff --git a/giambio/abstractions.py b/giambio/abstractions.py index d3d26fd..16596f8 100644 --- a/giambio/abstractions.py +++ b/giambio/abstractions.py @@ -1,5 +1,5 @@ import types - +from .traps import join, sleep, want_read, want_write, cancel class Result: """A wrapper for results of coroutines""" diff --git a/giambio/core.py b/giambio/core.py index 1b972d0..d8b6a2a 100644 --- a/giambio/core.py +++ b/giambio/core.py @@ -7,9 +7,9 @@ from .exceptions import AlreadyJoinedError, CancelledError from timeit import default_timer from time import sleep as wait from .socket import AsyncSocket, WantRead, WantWrite -from .traps import join, sleep, want_read, want_write, cancel from .abstractions import Task, Result from socket import SOL_SOCKET, SO_ERROR +from .traps import join, sleep, want_read, want_write, cancel class EventLoop: @@ -53,7 +53,7 @@ class EventLoop: self.running.result = Result(e.args[0] if e.args else None, None) # Saves the return value self.to_run.extend(self.joined.pop(self.running, ())) # Reschedules the parent task except RuntimeError: - self.to_run.extend(self.joined.pop(self.running, ())) + self.to_run.extend(self.joined.pop(self.running, ())) # Reschedules the parent task self.to_run.append(self.running) except Exception as has_raised: self.to_run.extend(self.joined.pop(self.running, ())) # Reschedules the parent task @@ -116,8 +116,6 @@ class EventLoop: await want_read(sock) return sock.accept() - - async def sock_sendall(self, sock: socket.socket, data: bytes): """Sends all the passed data, as bytes, trough the socket asynchronously""" @@ -151,11 +149,11 @@ class EventLoop: self.to_run.append(self.running) # Reschedule the task that called sleep def want_cancel(self, task): - self.to_run.extend(self.joined.pop(self.running, ())) # Reschedules the parent task task.cancelled = True + self.to_run.extend(self.joined.pop(self.running, ())) + self.to_run.append(self.running) # Reschedules the parent task task.throw(CancelledError()) - async def connect_sock(self, sock: socket.socket, addr: tuple): try: # "Borrowed" from curio result = sock.connect(addr) diff --git a/giambio/exceptions.py b/giambio/exceptions.py index fc74c6e..24d3ead 100644 --- a/giambio/exceptions.py +++ b/giambio/exceptions.py @@ -12,3 +12,6 @@ class CancelledError(GiambioError): def __repr__(self): return "giambio.exceptions.CancelledError" + +class TaskCancelled(GiambioError): + """This exception is raised when the user attempts to join a cancelled task""" \ No newline at end of file diff --git a/giambio/traps.py b/giambio/traps.py index 9b11ce4..9f45c94 100644 --- a/giambio/traps.py +++ b/giambio/traps.py @@ -2,8 +2,7 @@ import types import socket -from .abstractions import Task - +from .exceptions import TaskCancelled @types.coroutine def sleep(seconds: int): @@ -35,16 +34,18 @@ def want_write(sock: socket.socket): @types.coroutine -def join(task: Task): +def join(task): """'Tells' the scheduler that the desired task MUST be awaited for completion""" + if task.cancelled: + raise TaskCancelled("Cannot join cancelled task!") task.joined = True yield "want_join", task return task.get_result() # This raises an exception if the child task errored @types.coroutine -def cancel(task: Task): +def cancel(task): """'Tells' the scheduler that the passed task must be cancelled""" yield "want_cancel", task diff --git a/test.py b/test.py index a3cc91e..8308fb4 100644 --- a/test.py +++ b/test.py @@ -3,7 +3,6 @@ from giambio.socket import AsyncSocket import socket import logging - loop = giambio.core.EventLoop() logging.basicConfig(level=20,