mirror of https://github.com/nocturn9x/giambio.git
Many fixes, many TODOs added
This commit is contained in:
parent
9f4346b430
commit
f9eb329ec9
|
@ -4,17 +4,17 @@ loop = giambio.EventLoop()
|
|||
|
||||
"""
|
||||
|
||||
What works and what does not (23rd March 2020 23:24 PM)
|
||||
What works and what does not (25th March 2020 20:35)
|
||||
|
||||
- Run tasks concurrently: V
|
||||
- Join mechanism: V
|
||||
- Sleep mechanism: V
|
||||
- Cancellation mechanism: X Note: Figure out how to rescheule parent task
|
||||
- Cancellation mechanism: V
|
||||
- Exception propagation: V
|
||||
- Concurrent I/O: V
|
||||
- Return values of coroutines: V
|
||||
- Scheduling tasks for future execution: V
|
||||
- Task Spawner (context manager): X Note: Not Implemented
|
||||
- Task Spawner (context manager): V
|
||||
|
||||
"""
|
||||
|
||||
|
@ -28,7 +28,7 @@ async def countdown(n):
|
|||
return "Count DOWN over"
|
||||
except giambio.CancelledError:
|
||||
print("countdown cancelled!")
|
||||
|
||||
raise Exception("Oh no!") #TODO Propagate this
|
||||
|
||||
async def count(stop, step=1):
|
||||
try:
|
||||
|
@ -44,13 +44,16 @@ async def count(stop, step=1):
|
|||
|
||||
|
||||
async def main():
|
||||
try:
|
||||
print("Spawning countdown immediately, scheduling count for 4 secs from now")
|
||||
async with giambio.TaskManager(loop) as manager:
|
||||
task = await manager.spawn(countdown(4))
|
||||
await manager.schedule(count(8, 2), 4)
|
||||
task = manager.spawn(countdown(4))
|
||||
manager.schedule(count(8, 2), 4)
|
||||
await task.cancel()
|
||||
for task, ret in manager.values.items():
|
||||
print(f"Function '{task.coroutine.__name__}' at {hex(id(task.coroutine))} returned an object of type '{type(ret).__name__}': {repr(ret)}")
|
||||
|
||||
except: # TODO: Fix this, see above
|
||||
pass
|
||||
|
||||
loop.start(main)
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ from .socket import AsyncSocket, WantRead, WantWrite
|
|||
from .abstractions import Task, Result
|
||||
from socket import SOL_SOCKET, SO_ERROR
|
||||
from .traps import _join, _sleep, _want_read, _want_write, _cancel
|
||||
from .util import TaskManager
|
||||
|
||||
|
||||
class EventLoop:
|
||||
|
@ -59,9 +60,7 @@ class EventLoop:
|
|||
self.to_run.extend(self.joined.pop(self.running, ())) # Reschedules the parent task
|
||||
except Exception as has_raised:
|
||||
self.to_run.extend(self.joined.pop(self.running, ())) # Reschedules the parent task
|
||||
if self.running.joined: # Let the join function handle the hassle of propagating the error
|
||||
self.running.result = Result(None, has_raised) # Save the exception
|
||||
else: # Let the exception propagate (I'm looking at you asyncIO ;))
|
||||
raise
|
||||
except KeyboardInterrupt:
|
||||
self.running.throw(KeyboardInterrupt)
|
||||
|
@ -70,7 +69,7 @@ class EventLoop:
|
|||
def start(self, coroutine: types.coroutine, *args, **kwargs):
|
||||
"""Starts the event loop"""
|
||||
|
||||
self.to_run.append(coroutine(*args, **kwargs))
|
||||
TaskManager(self).spawn(coroutine(*args, **kwargs))
|
||||
self.loop()
|
||||
|
||||
def want_read(self, sock: socket.socket):
|
||||
|
@ -124,6 +123,7 @@ class EventLoop:
|
|||
coroutine returns or, if an exception gets raised, the exception will get propagated inside the
|
||||
parent task"""
|
||||
|
||||
|
||||
if coro not in self.joined:
|
||||
self.joined[coro].append(self.running)
|
||||
else:
|
||||
|
@ -137,11 +137,12 @@ class EventLoop:
|
|||
self.to_run.append(self.running) # Reschedule the task that called sleep
|
||||
|
||||
def want_cancel(self, task):
|
||||
task.cancelled = True
|
||||
self.to_run.extend(self.joined.pop(self.running, ()))
|
||||
self.to_run.append(self.running) # Reschedules the parent task
|
||||
# task.cancelled = True
|
||||
task.throw(CancelledError())
|
||||
|
||||
|
||||
async def connect_sock(self, sock: socket.socket, addr: tuple):
|
||||
try: # "Borrowed" from curio
|
||||
result = sock.connect(addr)
|
||||
|
|
|
@ -72,5 +72,6 @@ def _cancel(task):
|
|||
be cancelled at any time
|
||||
"""
|
||||
|
||||
task.cancelled = True
|
||||
yield "want_cancel", task
|
||||
|
||||
|
|
|
@ -18,18 +18,23 @@ class TaskManager:
|
|||
async def __aenter__(self):
|
||||
return self
|
||||
|
||||
async def __aexit__(self, *args):
|
||||
for task in self.tasks:
|
||||
if task.cancelled:
|
||||
self.values[task] = CancelledError()
|
||||
async def __aexit__(self, type, value, traceback):
|
||||
if type:
|
||||
# TODO: Handle exceptions here
|
||||
...
|
||||
else:
|
||||
self.values[task] = await task.join(self.silent)
|
||||
for task in self.tasks:
|
||||
if not task.cancelled:
|
||||
self.values[task] = await task.join()
|
||||
else:
|
||||
self.values[task] = CancelledError()
|
||||
|
||||
def spawn(self, coroutine: types.coroutine):
|
||||
"""Schedules a task for execution, appending it to the call stack"""
|
||||
|
||||
task = Task(coroutine, self)
|
||||
self.loop.to_run.append(task)
|
||||
self.tasks.append(task)
|
||||
return task
|
||||
|
||||
def schedule(self, coroutine: types.coroutine, when: int):
|
||||
|
@ -37,5 +42,6 @@ class TaskManager:
|
|||
|
||||
self.loop.sequence += 1
|
||||
task = Task(coroutine, self)
|
||||
self.tasks.append(task)
|
||||
heappush(self.loop.paused, (self.loop.clock() + when, self.loop.sequence, task))
|
||||
return task
|
||||
|
|
Loading…
Reference in New Issue