|
|
|
@ -17,6 +17,9 @@ import socket |
|
|
|
|
cdef gpr_timespec _GPR_INF_FUTURE = gpr_inf_future(GPR_CLOCK_REALTIME) |
|
|
|
|
cdef float _POLL_AWAKE_INTERVAL_S = 0.2 |
|
|
|
|
|
|
|
|
|
# This bool indicates if the event loop impl can monitor a given fd, or has |
|
|
|
|
# loop.add_reader method. |
|
|
|
|
cdef bint _has_fd_monitoring = True |
|
|
|
|
|
|
|
|
|
IF UNAME_SYSNAME == "Windows": |
|
|
|
|
cdef void _unified_socket_write(int fd) nogil: |
|
|
|
@ -41,17 +44,29 @@ cdef class BaseCompletionQueue: |
|
|
|
|
cdef class _BoundEventLoop: |
|
|
|
|
|
|
|
|
|
def __cinit__(self, object loop, object read_socket, object handler): |
|
|
|
|
global _has_fd_monitoring |
|
|
|
|
self.loop = loop |
|
|
|
|
self.read_socket = read_socket |
|
|
|
|
reader_function = functools.partial( |
|
|
|
|
handler, |
|
|
|
|
loop |
|
|
|
|
) |
|
|
|
|
self.loop.add_reader(self.read_socket, reader_function) |
|
|
|
|
# NOTE(lidiz) There isn't a way to cleanly pre-check if fd monitoring |
|
|
|
|
# support is available or not. Checking the event loop policy is not |
|
|
|
|
# good enough. The application can has its own loop implementation, or |
|
|
|
|
# uses different types of event loops (e.g., 1 Proactor, 3 Selectors). |
|
|
|
|
if _has_fd_monitoring: |
|
|
|
|
try: |
|
|
|
|
self.loop.add_reader(self.read_socket, reader_function) |
|
|
|
|
self._has_reader = True |
|
|
|
|
except NotImplementedError: |
|
|
|
|
_has_fd_monitoring = False |
|
|
|
|
self._has_reader = False |
|
|
|
|
|
|
|
|
|
def close(self): |
|
|
|
|
if self.loop: |
|
|
|
|
self.loop.remove_reader(self.read_socket) |
|
|
|
|
if self._has_reader: |
|
|
|
|
self.loop.remove_reader(self.read_socket) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cdef class PollerCompletionQueue(BaseCompletionQueue): |
|
|
|
@ -97,7 +112,14 @@ cdef class PollerCompletionQueue(BaseCompletionQueue): |
|
|
|
|
self._queue_mutex.lock() |
|
|
|
|
self._queue.push(event) |
|
|
|
|
self._queue_mutex.unlock() |
|
|
|
|
_unified_socket_write(self._write_fd) |
|
|
|
|
if _has_fd_monitoring: |
|
|
|
|
_unified_socket_write(self._write_fd) |
|
|
|
|
else: |
|
|
|
|
with gil: |
|
|
|
|
# Event loops can be paused or killed at any time. So, |
|
|
|
|
# instead of deligate to any thread, the polling thread |
|
|
|
|
# should handle the distribution of the event. |
|
|
|
|
self._handle_events(None) |
|
|
|
|
|
|
|
|
|
def _poll_wrapper(self): |
|
|
|
|
with nogil: |
|
|
|
@ -119,7 +141,10 @@ cdef class PollerCompletionQueue(BaseCompletionQueue): |
|
|
|
|
self._write_socket.close() |
|
|
|
|
|
|
|
|
|
def _handle_events(self, object context_loop): |
|
|
|
|
cdef bytes data = self._read_socket.recv(1) |
|
|
|
|
cdef bytes data |
|
|
|
|
if _has_fd_monitoring: |
|
|
|
|
# If fd monitoring is working, clean the socket without blocking. |
|
|
|
|
data = self._read_socket.recv(1) |
|
|
|
|
cdef grpc_event event |
|
|
|
|
cdef CallbackContext *context |
|
|
|
|
|
|
|
|
|