<commit_before>"""epoll loop backend

This module is deprecated and will be removed once pyuv_cffi is fully implemented.
"""
import logging
import heapq
import select
import errno

from .. import patcher
from ..const import READ, WRITE
from ..support import compat, get_errno
from . import abc
from .watchers import PollFdListener
from .timer import Timer

compat.patch()

log = logging.getLogger('guv')

epoll = patcher.original('select').epoll
time = patcher.original('time')
queue = patcher.original('queue')

EXC_MASK = select.POLLERR | select.POLLHUP
READ_MASK = select.POLLIN | select.POLLPRI
WRITE_MASK = select.POLLOUT
SYSTEM_EXCEPTIONS = (KeyboardInterrupt, SystemExit)


class Hub(abc.AbstractHub):
    def __init__(self):
        super().__init__()
        self.Listener = PollFdListener
        self.stopping = False
        self.running = False
        self.timers = []  # heap of timers
        self.callbacks = []  # list of callbacks
        self.epoll = epoll()

    def _fire_timers(self, up_to):
        """Fire timers scheduled to be fire before `up_to`

        :param float up_to: timers scheduled to be fired before this specified absolute time
            (seconds) will be fired
        """
        timers = self.timers

        while timers:
            timer = timers[0]

            if timer.called:
                heapq.heappop(timers)
                continue

            if timer > up_to:
                break

            if timer.absolute_time > time.monotonic():
                break

            # call the timer to call the callback
            timer()

            heapq.heappop(timers)

    def _time_until_next_timer(self):
        """Get number of seconds until next timer has to be fired
        """
        if not self.timers:
            return None

        return self.timers[0].absolute_time - time.monotonic()

    def _remove_descriptor(self, fd):
        #: :type: dict[fd, listener]
        readers = self.listeners[READ]
        #: :type: dict[fd, listener]
        writers = self.listeners[WRITE]

        if fd in readers:
            del readers[fd]

        if fd in writers:
            del writers[fd]

    def _fire_callbacks(self):
        """Fire immediate callbacks
        """
        callbacks = self.callbacks
        self.callbacks = []
        for cb, args, kwargs in callbacks:
            cb(*args, **kwargs)

    def run(self):
        if self.stopping:
            return

        if self.running:
            raise RuntimeError("The hub's runloop is already running")

        log.debug('Start runloop')
        try:
            self.running = True
            self.stopping = False
            self._run_loop()
        finally:
            self.running = False
            self.stopping = False

    def _run_loop(self):
        try:
            while True:
                self._fire_timers(time.monotonic())
                self._fire_callbacks()
                sleep_time = self._time_until_next_timer() or 60
                self._wait(sleep_time)

        except KeyboardInterrupt:
            self.abort()<commit_msg>Add inline comments for clarity<commit_after>"""epoll loop backend

This module is deprecated and will be removed once pyuv_cffi is fully implemented.
"""
import logging
import heapq
import select
import errno

from .. import patcher
from ..const import READ, WRITE
from ..support import compat, get_errno
from . import abc
from .watchers import PollFdListener
from .timer import Timer

compat.patch()

log = logging.getLogger('guv')

epoll = patcher.original('select').epoll
time = patcher.original('time')
queue = patcher.original('queue')

EXC_MASK = select.POLLERR | select.POLLHUP
READ_MASK = select.POLLIN | select.POLLPRI
WRITE_MASK = select.POLLOUT
SYSTEM_EXCEPTIONS = (KeyboardInterrupt, SystemExit)


class Hub(abc.AbstractHub):
    def __init__(self):
        super().__init__()
        self.Listener = PollFdListener
        self.stopping = False
        self.running = False
        self.timers = []  # heap of timers
        self.callbacks = []  # list of callbacks
        self.epoll = epoll()

    def _fire_timers(self, up_to):
        """Fire timers scheduled to be fire before `up_to`

        :param float up_to: timers scheduled to be fired before this specified absolute time
            (seconds) will be fired
        """
        timers = self.timers

        while timers:
            timer = timers[0]

            if timer.called:
                heapq.heappop(timers)
                continue

            if timer > up_to:
                break

            if timer.absolute_time > time.monotonic():
                break

            # call the timer to call the callback
            timer()

            heapq.heappop(timers)

    def _time_until_next_timer(self):
        """Get number of seconds until next timer has to be fired
        """
        if not self.timers:
            return None

        return self.timers[0].absolute_time - time.monotonic()

    def _remove_descriptor(self, fd):
        #: :type: dict[fd, listener]
        readers = self.listeners[READ]
        #: :type: dict[fd, listener]
        writers = self.listeners[WRITE]

        if fd in readers:
            del readers[fd]

        if fd in writers:
            del writers[fd]

    def _fire_callbacks(self):
        """Fire immediate callbacks
        """
        callbacks = self.callbacks
        self.callbacks = []
        for cb, args, kwargs in callbacks:
            cb(*args, **kwargs)

    def run(self):
        if self.stopping:
            return

        if self.running:
            raise RuntimeError("The hub's runloop is already running")

        log.debug('Start runloop')
        try:
            self.running = True
            self.stopping = False
            self._run_loop()
        finally:
            self.running = False
            self.stopping = False

    def _run_loop(self):
        try:
            while True:
                self._fire_timers(time.monotonic())
                self._fire_callbacks()  # call scheduled callbacks (spawn(), etc.)
                sleep_time = self._time_until_next_timer() or 60
                self._wait(sleep_time)  # call I/O event callbacks

        except KeyboardInterrupt:
            self.abort()
{'fraction_non_alphanumeric': 0.08600953895071542, 'fraction_numerical': 0.0012718600953895071, 'mean_word_length': 1.9452247191011236, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1952940', 'n_tokens_mistral': 1800, 'n_tokens_neox': 1739, 'n_words': 508}