You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
67 lines
1.5 KiB
67 lines
1.5 KiB
import asyncio
|
|
import functools
|
|
|
|
global_signals = {}
|
|
|
|
|
|
async def emit(signal, payload=None):
|
|
for q in global_signals.get(signal, []):
|
|
if payload is not None:
|
|
await q.put({"payload": payload})
|
|
else:
|
|
await q.put({})
|
|
|
|
|
|
async def a_shutdown():
|
|
for key in global_signals:
|
|
for q in global_signals[key]:
|
|
await q.put(None)
|
|
|
|
|
|
def shutdown(loop=None):
|
|
if loop is None:
|
|
loop = asyncio.get_event_loop()
|
|
loop.run_until_complete(a_shutdown())
|
|
|
|
|
|
async def consumer(queue, callback, signal):
|
|
while True:
|
|
item = await queue.get()
|
|
if item is None:
|
|
global_signals[signal].remove(queue)
|
|
break
|
|
if "payload" in item:
|
|
await callback(item["payload"])
|
|
else:
|
|
await callback()
|
|
|
|
class ListenerHandle:
|
|
def __init__(self, queue):
|
|
self.queue = queue
|
|
|
|
async def close(self):
|
|
await self.queue.put(None)
|
|
|
|
|
|
def listen_on(signal, fun=None, *, loop=None):
|
|
if loop is None:
|
|
loop = asyncio.get_event_loop()
|
|
|
|
def decorator(func, deco=True):
|
|
@functools.wraps(func)
|
|
def fun(*args, **kwargs):
|
|
return func(*args, **kwargs)
|
|
|
|
q = asyncio.Queue()
|
|
global_signals.setdefault(signal, []).append(q)
|
|
loop.call_soon(
|
|
lambda: asyncio.ensure_future(consumer(q, func, signal))
|
|
)
|
|
if deco:
|
|
return fun
|
|
else:
|
|
return ListenerHandle(q)
|
|
|
|
if fun is not None:
|
|
return decorator(fun, False)
|
|
return decorator
|
|
|