Source code for botlib.engine

# mad/engine.py
#
#

""" 
    a engine is select.epoll event loop, easily interrup_table
    esp. versus a blocking event loop.

"""

from .error import EDISCONNECT, ERESUME
from .launcher import Launcher
from .handler import Handler
from .object import Object
from .register import Register

import logging
import select
import queue
import time

READ_ONLY = select.POLLIN | select.POLLPRI | select.POLLHUP | select.POLLERR
READ_WRITE = READ_ONLY | select.POLLOUT

[docs]class Engine(Launcher): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._connected.clear() self._handlers = Register() self._queue = queue.Queue() self._poll = select.epoll() self._resume = Object() self._state.status = "running" self._time.start = time.time()
[docs] def dispatch(self, event): event.parse() for handler in self._handlers.get(event._parsed.cmnd, []): handler(event)
[docs] def select(self): while self._state.status: for event in self.events(): if not event: break self._counter.events = self._counter.events + 1 self.launch(self.dispatch, event, name=event._parsed.txt) self._time.latest = time.time()
[docs] def events(self): fdlist = self._poll.poll() for fd, event in fdlist: try: yield self.event() except (ConnectionResetError, BrokenPipeError, EDISCONNECT) as ex: self.connect()
[docs] def register_fd(self, f): try: fd = f.fileno() except: fd = f if not fd: return fd logging.warn("# engine on %s" % str(fd)) self._poll.register(fd, READ_ONLY) self._resume.fd = fd return fd
[docs] def resume(self): if not self._resume.fd: raise bot.error.ERESUME logging.info("# resume on %s" % self._resume.fd) self._poll = select.epoll.fromfd(self._resume.fd)
[docs] def start(self, *args, **kwargs): super().start() self.launch(self.select)
[docs] def stop(self): self._status = "" self._poll.close()